Журнал LinuxFormat - перейти на главную

LXF167:Гру­зить­ся бы­ст­рее

Материал из Linuxformat
Перейти к: навигация, поиск

Управ­ле­ние сис­те­мой. Зна­комь­тесь с за­ме­ной init и сопутствующим ин­ст­ру­мен­та­ри­ем

Содержание

Systemd: С­ко­ре­е за­гружаемся

До­лой ста­рое, да­ешь но­вое. По­ра го­во­рить «init, про­щай». Джон Лэйн ус­ко­ря­ет за­груз­ку, дос­ти­гая боль­шей сте­пе­ни кон­тро­ля – бла­го­да­ря systemd.

(thumbnail)
Наш эксперт Джон Лэйн впер­вые за­брел в Linux еще в 1994 го­ду, да там и ос­тал­ся. Он и не упом­нит, ко­гда в по­след­ний раз прибегал к Windows.

В те­чение мно­гих лет в осно­ве скром­ной ОС на ба­зе Unix ле­жал про­цесс, на­зы­вае­мый init – инициа­ли­за­ция в ее серд­це. Яд­ро вру­ча­ет ему кон­троль за про­цес­сом за­груз­ки, по­сле че­го он ста­но­вит­ся ро­ди­те­лем всех про­цес­сов, что от­ра­же­но в ста­ту­се его PID (иден­ти­фи­ка­то­ра про­цес­са), ко­то­рый ра­вен 1. Но в ско­ром вре­мени это из­менит­ся, по­то­му что уже есть systemd, ко­то­рый на­всегда завоюет PID 1. Мы рас­смот­рим осно­вы systemd, ко­то­рые сле­ду­ет понимать, ес­ли ва­ша ОС пе­ре­хо­дит от init к systemd. По хо­ду де­ла мы так­же пред­ста­вим неко­то­рые по­лез­ные сред­ст­ва ад­минист­ри­ро­вания, ко­то­рые вклю­ча­ет systemd.

Systemd, то есть «сис­тем­ный де­мон» – это но­вый менед­жер сис­те­мы и служб в Linux. Для конеч­ных поль­зо­ва­те­лей самое за­мет­ное его проявление – бы­ст­рая за­груз­ка, что свя­за­но с его асин­хрон­ной при­ро­дой, в корне от­ли­чной от син­хрон­но­го про­цес­са init, при ко­то­ром за­да­чи вы­пол­ня­ют­ся од­на за дру­гой.

При за­пуске ком­пь­ю­те­ра его за­груз­чик (на­при­мер, Grub) за­гру­жа­ет яд­ро Linux в па­мять и пе­ре­да­ет ему управ­ление. Яд­ро вы­пол­ня­ет свои соб­ст­вен­ные про­цес­сы инициа­ли­за­ции, в том чис­ле мон­ти­ро­вание корневой фай­ло­вой сис­те­мы, и толь­ко по­сле это­го за­пуска­ет /sbin/init. Это пер­вый про­цесс, на­ча­тый в сис­те­ме, и, сле­до­ва­тель­но, ему при­сваи­ва­ет­ся PID 1. А вот при ис­поль­зо­вании systemd /sbin/init яв­ля­ет­ся сим­во­ли­че­­ской ссыл­кой на дво­ич­ный файл systemd, и вме­сто init яд­ро за­пуска­ет systemd.

Та­ким об­ра­зом, пер­вое су­ще­ст­вен­ное раз­ли­чие со­сто­ит в от­сут­ст­вии init. Оно оз­на­ча­ет, что /etc/inittab, а так­же весь на­бор скрип­тов /etc/rc.d и сим­во­ли­че­­ских ссы­лок, ис­поль­зую­щих­ся для за­груз­ки и под­дер­жания сис­те­мы, стал из­бы­точ­ным. Вы мо­же­те об­на­ру­жить, что неко­то­рые скрип­ты rc.d все еще су­ще­ст­ву­ют, так как мно­гие па­ке­ты их вклю­ча­ют для обес­пе­чения ра­бо­ты в сис­те­мах на ба­зе init. Но systemd их иг­но­ри­ру­ет.

Вме­сто это­го, в systemd ис­поль­зу­ют­ся юниты [units]. Это основ­ные объ­ек­ты, ко­то­ры­ми управ­ля­ет systemd, и они мо­гут пред­став­лять со­бой служ­бы, уст­рой­ст­ва, точ­ки мон­ти­ро­вания, тай­ме­ры и дру­гие ком­понен­ты сис­те­мы. Юниты оп­ре­де­ля­ют­ся фай­ла­ми на­строй­ки, ко­то­рые на­хо­дят­ся ли­бо в /lib/systemd/system, ли­бо в /etc/systemd/system, при­чем по­след­ний кор­рек­ти­ру­ет пер­вый и пред­на­зна­че­н для ис­поль­зо­вания локаль­ны­ми ад­минист­ра­то­ра­ми – ес­ли вы пи­ше­те или из­ме­няе­те фай­лы на­строй­ки юнитов, нуж­но раз­ме­щать их там.

Пер­вые ви­ды юнитов, ко­то­рые вы долж­ны понимать – це­ле­вые объ­ек­ты и служ­бы. Це­ле­вые объ­ек­ты – это systemd-эк­ви­ва­лен­ты кон­цеп­ции уров­ня вы­полнения sysvinit, а служ­бы оп­ре­де­ля­ют, как сис­те­ма управ­ля­ет про­цес­са­ми.

Уровни бы­ли груп­па­ми про­цес­сов, ко­то­ры­ми управ­лял де­мон init. Уро­вень 3 обес­пе­чи­вал за­груз­ку основ­ной сис­те­мы, тогда как 5-й уро­вень пре­достав­лял гра­фи­че­­ский ра­бо­чий стол, а уро­вень 0 оста­нав­ли­вал сис­те­му. В слу­чае systemd за­да­чи име­ют на­звания – что де­ла­ет их бо­лее чи­тае­мы­ми (юниты, эк­ви­ва­лент­ные уров­ням 3 и 5, на­зы­ва­ют­ся multi-user.target и graphical.target).

Це­ле­вой объ­ект по умол­чанию

За­пуская сис­те­му, systemd ак­ти­ви­зи­ру­ет свой це­ле­вой объ­ект по умол­чанию, ко­то­рый на­зы­ва­ет­ся default.target. Это эк­ви­ва­лент уров­ня за­пуска по умол­чанию init, ко­то­рый был бы ука­зан в in/etc/inittab. При ис­поль­зо­вании systemd, default.target яв­ля­ет­ся сим­во­ли­че­­ской ссыл­кой на необ­хо­ди­мые це­ле­вые объ­ек­ты, обыч­но multi-user.target или graphical. Для systemd, из­менение уров­ня вы­полнения по умол­чанию – это все­го лишь во­прос за­ме­ны сим­во­ли­че­­ской ссыл­ки:

$ ln -sf /lib/systemd/system/multi-user.target /etc/systemd/ system/default.target

Мож­но так­же пе­ре­оп­ре­де­лить це­ле­вые объ­ек­ты по умол­чанию, до­ба­вив в яд­ро оп­цию команд­ной стро­ки systemd.unit= пе­ред за­груз­кой (на­жав е в ме­ню за­гру­зоч­но­го эк­ра­на Grub).

Для тех, кто зна­ком с уров­ня­ми за­пуска, systemd пре­достав­ля­ет це­ле­вые объ­ек­ты (это про­сто сим­во­ли­че­­ские ссыл­ки на эк­ви­ва­лент­ные це­ле­вые объ­ек­ты systemd), а так­же под­дер­жи­ва­ет ко­ман­ду telinit для из­менения уровней. На­при­мер, вы мо­же­те про­дол­жать ис­поль­зо­вать telinit 0 для вы­клю­чения. Но ко­ман­да systemd, с по­мо­щью ко­то­рой это де­ла­ет­ся, немно­го удобнее для чтения:

$ systemctl poweroff

Или же, для из­ме­не­ния уров­ня за­пус­ка:

$ systemctl isolate multi-user.target

Вы ис­поль­зуе­те systemctl во взаи­мо­дей­ст­вии с де­мо­ном systemd. Его ко­ман­да isolate за­пуска­ет дан­ный це­ле­вой объ­ект и оста­нав­ли­ва­ет все, что не яв­ля­ет­ся за­ви­си­мо­стью это­го но­во­го це­ле­во­го объ­ек­та (точ­но так же, как при из­менении уров­ня за­пуска в sysvinit).

За­да­чей це­ле­во­го объ­ек­та яв­ля­ет­ся груп­пи­ро­вание свя­зан­ных единиц та­ким об­ра­зом, что­бы они управ­ля­лись как еди­ное це­лое. Со­от­вет­ст­вую­щие юниты за­да­ют­ся в ви­де за­ви­си­мо­стей, что­бы по­сле их ак­ти­ва­ции все за­ви­си­мо­сти так­же бы­ли ак­ти­ви­зи­ро­ва­ны. Юнит мож­но на­стро­ить та­ким об­ра­зом, что­бы до за­пуска он ждал го­тов­но­сти дру­го­го юнита. Од­на­ко од­ной из це­лей раз­ра­бот­ки systemd бы­ло снижение по­треб­но­сти в та­ких за­ви­си­мо­стях, что­бы рас­па­рал­ле­лить про­цес­сы в как мож­но боль­шей сте­пени. Рас­смот­рим кон­фи­гу­ра­цию мно­го­поль­зо­ва­тель­ско­го це­ле­во­го объ­ек­та:

$ cat /lib/systemd/system/multi-user.target

[Unit]

Description=Multi-User

Documentation=man:systemd.special(7)

Requires=basic.target

Conflicts=rescue.service rescue.target

After=basic.target rescue.service rescue.target

AllowIsolate=yes

[Install]

Alias=default.target

Файл со­дер­жит име­но­ван­ные бло­ки: [unit] со­дер­жит па­ра­мет­ры, дей­ст­ви­тель­ные для всех ти­пов юнитов, а [Install] со­об­ща­ет systemd, ка­ким об­ра­зом уста­но­вить це­ле­вые объ­ек­ты (это мы рас­смот­рим поз­же). Файл в неко­то­рой сте­пени яв­ля­ет­ся са­мо­оче­вид­ным: в нем го­во­рит­ся, что за­ви­си­мо­стью мно­го­поль­зо­ва­тель­ско­го це­ле­во­го объ­ек­та яв­ля­ет­ся basic.target, что он кон­флик­ту­ет с це­ле­вы­ми объ­ек­та­ми rescue.service и rescue.target (они бу­дут оста­нов­ле­ны, когда за­пустит­ся этот юнит), и что он не за­пустит­ся, по­ка не бу­дет за­пу­щен basic.target. AllowIsolate со­об­ща­ет systemd, что этот юнит мо­жет быть ис­поль­зо­ван в ко­ман­де systemctl isolate, опи­сан­ной вы­ше (т. е. на­по­до­бие уров­ня за­пуска sysvinit).

Юниты, пе­ре­чис­лен­ные в за­ви­си­мо­сти Requires [Тре­бу­ет­ся], бу­дут ак­ти­ви­зи­ро­ва­ны в ре­зуль­та­те ак­ти­ва­ции це­ле­во­го объ­ек­та. Ес­ли ка­кие-ли­бо из этих за­ви­си­мо­стей не удов­ле­тво­ре­ны, це­ле­вой объ­ект так­же не сра­бо­та­ет. Есть и аль­тер­на­тив­ная фор­ма за­ви­си­мо­сти, менее же­ст­кая, чем Requires, под на­званием Wants [Же­ла­тель­но]. В свя­зи с этой за­ви­си­мо­стью, от­каз не при­во­дит к сбою це­ле­во­го объ­ек­та. За­ви­си­мо­сти мо­гут быть ука­за­ны в фай­ле на­строй­ки юнита, а так­же пу­тем соз­дания сим­во­ли­че­­ских ссы­лок в ка­та­ло­ге по имени юнита и за­ви­си­мо­сти:

$ ls -l /{lib,etc}/systemd/system/multi-user.target.*

/etc/systemd/system/multi-user.target.wants/: total 0

fcron.service -> /usr/lib/systemd/system/fcron.service

lxc.target -> /etc/systemd/system/lxc.target

netcfg@bridge.service -> /usr/lib/systemd/system/netcfg@.service

ntpd.service -> /usr/lib/systemd/system/ntpd.service

remote-fs.target -> /usr/lib/systemd/system/remote-fs.target

sshdgenkeys.service -> /usr/lib/systemd/system/ sshdgenkeys.service

sshd.service -> /usr/lib/systemd/system/sshd.service /lib/systemd/system/multi-ser.target.wants/:

total 0

dbus.service -> ../dbus.service

getty.target -> ../getty.target

systemd-ask-password-wall.path -> ../systemd-ask-password- wall.path

systemd-logind.service -> ../systemd-logind.service

systemd-user-sessions.service -> ../systemd-user-sessions.service

В этом вы­во­де два ка­та­ло­га, со­дер­жа­щих за­ви­си­мо­сти ти­па Wants. Ка­ж­дая из этих за­ви­си­мо­стей ак­ти­ви­зи­ру­ет­ся тогда, когда ак­ти­ви­зи­ру­ет­ся multi-user.target. Вы мо­же­те са­ми соз­дать по­доб­ные сим­во­ли­че­­ские ссыл­ки ко­ман­дой ln -s, или же systemd мо­жет соз­дать их для вас:

$ systemctl enable sshd.service

– это эк­ви­ва­лент­но

ln -s ‘/usr/lib/systemd/system/sshd.socket’ ‘/etc/systemd/’

Ко­ман­да systemctl enable по­ру­ча­ет systemd вы­полнение за­дач, пе­ре­чис­лен­ных в раз­де­ле [Install] фай­ла на­строй­ки юнита. На­при­мер, кон­фи­гу­ра­ция служ­бы SSH со­дер­жит сле­дую­щее:

[Install]

WantedBy=multi-user.target

Also=sshdgenkeys.service

Здесь от systemd тре­бу­ют­ся две ве­щи: соз­дать сим­во­ли­че­скую ссыл­ку на за­ви­си­мо­сти Wants и уста­но­вить до­полнитель­ные служ­бы sshgenkeys (как это сде­лать, опи­са­но в его соб­ст­вен­ном фай­ле на­строй­ки, sshgenkeys.service). Об­рат­ным про­цес­сом яв­ля­ет­ся systemctl disable, про­ти­во­по­лож­ный про­цес­су systemctl enable. Уч­ти­те, что когда systemctl ак­ти­ви­зи­ру­ет или оста­нав­ли­ва­ет юнит, он его не вклю­ча­ет и не вы­клю­ча­ет. Вновь ак­ти­ви­ро­ван­ная служ­ба бу­дет вклю­че­на при сле­дую­щей за­груз­ке сис­те­мы. Что­бы вы­полнить это немед­лен­но, есть ко­ман­ды start и stop:

$ systemctl start sshd.service

Ес­ли вам нуж­но нечто бо­лее дей­ст­вен­ное, чем ко­ман­да stop, от­пра­вьте сиг­нал kill (или лю­бой дру­гой). Убь­ет служ­бу ко­ман­да

$ systemctl kill sshd.service

ко­то­рая от­прав­ля­ет сигнал SIGTERM. Ес­ли ну­жен дру­гой сиг­нал, ука­жи­те его (вы мо­же­те ис­поль­зо­вать имя с пре­фик­сом SIG или без него, или же но­мер сиг­на­ла; та­ким об­ра­зом, SIGTERM, TERM и 15 эк­ви­ва­лент­ны):

$ systemctl kill -s HUP sshd.service

Эта ко­ман­да kill по­сы­ла­ет сиг­нал всем про­цес­сам служ­бы. Од­на­ко вы мо­же­те вы­брать толь­ко основ­ной про­цесс:

$ systemctl kill -s HUP --kill-who=main sshd.service

Мы оз­на­ко­ми­лись с ак­ти­ва­ци­ей/оста­нов­кой и вклю­чением/вы­клю­чением служб. Су­ще­ст­ву­ет и тре­тий тип управ­ления – мас­ки­ров­ка [masking]. За­мас­ки­ро­ван­ная служ­ба – поч­ти то же, что и де­ак­ти­ви­ро­ван­ная, но ее нель­зя за­пустить вруч­ную. Маскировка де­лается соз­данием ссыл­ки фай­ла юнита на /dev/null:

$ ln -s /dev/null /etc/systemd/system/sshd.service

Systemd рас­по­зна­ет та­кие юниты и по­ка­зы­ва­ет их как «за­мас­ки­ро­ван­ные». Что­бы де­ма­ски­ро­вать служ­бу, про­сто уда­ли­те ссыл­ку. Как ука­зы­ва­лось вы­ше, служ­ба яв­ля­ет­ся про­цес­сом, управ­ляе­мым и кон­тро­ли­руе­мым systemd. Це­ле­вые юниты обычно ука­зы­ва­ют служ­бы как за­ви­си­мо­сти. На­при­мер, multi-user.target мо­жет ука­зы­вать sshd.service в ка­че­­ст­ве за­ви­си­мо­сти. Файл на­строй­ки юнита служ­бы уст­рой­ст­ва опи­сы­ва­ет, ка­ким об­ра­зом systemd дол­жен за­пускать и оста­нав­ли­вать служ­бы:

[Unit]

Description=OpenSSH Daemon Wants=sshdgenkeys.service After=sshdgenkeys.service

[Service]

ExecStart=/usr/sbin/sshd -D

ExecReload=/bin/kill -HUP $MAINPID

KillMode=process

Restart=always

[Install]

WantedBy=multi-user.target

Also=sshdgenkeys.service

Здесь опи­сы­ва­ет­ся служ­ба sshd. Ей нуж­на служ­ба sshgenkeys.service, и за­пуска­ет­ся она по ее го­тов­но­сти. Оп­ре­де­ле­на команд­ная стро­ка для за­пуска, оста­нов­ки и унич­то­жения де­мо­на sshd, плюс ука­зание на пе­ре­за­пуск де­мо­на, ес­ли тот пре­кра­тит ра­бо­ту.

Боль­шин­ст­во служб, как пра­ви­ло, од­но­эле­мент­ны, то есть в сис­те­ме ра­бо­та­ет толь­ко один эк­зем­п­ляр. Но есть служ­бы, вы­пол­няе­мые несколь­ко раз. Са­мый рас­про­стра­нен­ный при­мер – getty: эк­зем­п­ляр getty по­ро­ж­да­ет­ся для ка­ж­до­го из уст­ройств tty, ко­то­рые ис­поль­зу­ют под­сказ­ку для вхо­да в сис­те­му. Systemd под­дер­жи­ва­ет та­кие эк­зем­п­ля­ры служб и в его услов­ное име­но­вание вклю­ча­ет имя эк­зем­п­ля­ра: getty@tty1.service яв­ля­ет­ся эк­земп­ля­ром getty@.service. Ес­ли по­да­ет­ся ко­ман­да за­пуска getty@tty1.service, а фай­ла с та­ким именем нет, systemd оты­щет служ­бу getty@.service и за­пустит ее. Имя эк­зем­п­ля­ра, в дан­ном слу­чае tty1, ука­зы­ва­ет­ся в кон­фи­гу­ра­ции в ­виде за­полните­ля: %i.

Эк­зем­п­ля­ры можно ука­за­ть в ка­че­­ст­ве за­ви­си­мо­стей, пу­тем оп­ре­де­ления их как сим­во­ли­че­­ских ссы­лок:

$ ls -l /etc/systemd/system/getty.target.wants

getty@tty1.service -> /usr/lib/systemd/system/getty@.service

Или же они мо­гут быть за­пу­ще­ны вруч­ную, без на­строй­ки кон­крет­но­го эк­зем­п­ля­ра:

$ systemctl start getty@tty2.service

Ес­ли вы вно­си­те в кон­фи­гу­ра­цию сис­те­мы ка­кие-ли­бо из­ме­не­ния, на­до, что­бы systemd пе­ре­чи­тал свою кон­фи­гу­ра­цию:

$ systemctl daemon-reload

Иногда мо­жет тре­бо­вать­ся, что­бы служ­ба бы­ла доступ­ной, но для эф­фек­тив­но­го ис­поль­зо­вания ре­сур­сов за­пуска­лась толь­ко при необ­хо­ди­мости. Тра­ди­ци­он­ный спо­соб дости­жения это­го со­сто­ял в ис­поль­зо­вании де­мо­на вро­де inetd, ко­то­рый про­слу­ши­вал порт от имени служ­бы, а за­тем за­пускал служ­бу, когда к пор­ту был доступ. Ис­поль­зуя тип юнита socket, systemd под­дер­жи­ва­ет это как со­кет-ак­ти­ва­цию. В юнитах со­ке­тов опи­сы­ва­ет­ся со­кет, ко­то­рый systemd дол­жен про­слу­ши­вать. Ес­ли со­кет ис­поль­зу­ет­ся, то systemd за­пуска­ет свя­зан­ные с ним служ­бы (дол­жен су­ще­ст­во­вать файл на­строй­ки его юнита). Та­ким об­ра­зом, на­при­мер, мо­жет быть на­стро­ен де­мон SSH; в до­полнение к sshd.service, ко­то­рый мы рас­смот­ре­ли ранее, он име­ет так­же юнит sshd.socket. Файл sshd.socket со­дер­жит все­го несколь­ко строк:

[Unit]

Conflicts=sshd.service

Wants=sshdgenkeys.service

[Socket]

ListenStream=22

Accept=yes

[Install]

WantedBy=sockets.target

Раз­дел [Socket] по­ру­ча­ет systemd про­слу­ши­вать порт 22. Ес­ли на данный порт при­хо­дит па­кет, systemd немед­лен­но за­пустит юнит sshd.service, ко­то­рый по­сле это­го пе­ре­хва­ты­ва­ет со­кет. Со­кет-ак­ти­ва­ция мо­жет быть ис­поль­зо­ва­на для про­цес­сов, ко­то­рые ее под­дер­жи­ва­ют, ис­поль­зуя юнит со­ке­та как за­ви­си­мость це­ле­во­го объ­ек­та вме­сто юнита служ­бы. Про­цес­сы, ко­то­рые ра­бо­та­ют с inetd, так­же долж­ны ра­бо­тать с systemd. Та­ким об­ра­зом, что­бы за­пустить sshd че­рез со­кет-ак­ти­ва­цию, наш це­ле­вой объ­ект бу­дет за­ви­сеть от sshd.socket вме­сто sshd.service (тем не менее, по­следний так­же дол­жен су­ще­ст­во­вать).

Systemd ис­поль­зу­ет со­кет-ак­ти­ва­цию для раз­ре­шения па­рал­лель­но­го за­пуска за­ви­си­мых служб. Ес­ли ка­кой-ли­бо служ­бе тре­бу­ет­ся со­кет дру­гой служ­бы, дей­ст­ви­тель­но важ­но толь­ко то, что­бы со­кет су­ще­ст­во­вал тогда, когда он необ­хо­дим. При ис­поль­зо­вании со­кет-ак­ти­ва­ции для дости­жения этой це­ли systemd мо­жет обес­пе­чи­вать па­рал­лель­ное вы­полнение мно­гих дру­гих служб, что умень­ша­ет вре­мя за­груз­ки.

Systemd так­же под­дер­жи­ва­ет ак­ти­ва­цию по D-Bus. D-Bus – это сис­те­ма меж­про­цесс­но­го взаи­мо­дей­ст­вия со­об­щений ши­ны (www.freedesktop.org/wiki/Software/dbus), ши­ро­ко ис­поль­зуе­мой в на­столь­ных сре­дах, та­ких как Gnome и KDE, по­зво­ляя при­ло­жениям об­щать­ся. D-Bus име­ет соб­ст­вен­ные фай­лы .service, рас­по­ло­жен­ные в /usr/share/dbus-1/system-services, ко­то­рые оп­ре­де­ля­ют, ка­ким об­ра­зом за­пустить служ­бу, когда она по­на­до­бит­ся. D-Bus мо­жет вы­зы­вать ко­ман­ды управ­ления служ­ба­ми systemd. Это по­зво­ля­ет за­пустить неак­тив­ную служ­бу, когда она тре­бу­ет­ся на шине.

Что про­ис­хо­дит?

Systemd пре­достав­ля­ет ряд ин­ст­ру­мен­тов и средств, об­лег­чаю­щих сле­жение за тем, что про­ис­хо­дит внут­ри ва­шей сис­те­мы. Пер­вое, что вы мо­же­те сде­лать, это ис­поль­зо­вать ко­ман­ду systemctl, что­бы по­лу­чить об­щее пред­став­ление о ста­ту­сах всех юнитов. Са­ма по се­бе эта ко­ман­да пе­ре­чис­ля­ет все юниты, но вы мо­же­те ог­раничить вы­вод, ска­жем, все­ми це­ле­вы­ми объ­ек­та­ми:

$ systemctl --type target

Что­бы глуб­же изу­чить со­стоя­ние кон­крет­но­го юни­та, за­про­си­те его ста­тус:

$ systemctl status sshd.service

Эк­ран со­стояния по­ка­зы­ва­ет со­стояние юнита (в этом при­ме­ре – служ­бы sshd), а так­же по­следних 10 со­об­щений ее жур­на­ла.

Systemd раз­ме­ща­ет ка­ж­дый за­пускае­мый про­цесс в кон­троль­ной груп­пе, на­зван­ной по сво­ей служ­бе. Кон­троль­ные груп­пы – это функ­ция яд­ра, по­зво­ляю­щая ор­ганизо­вы­вать про­цес­сы ие­рар­хи­че­­ски, а так­же при­ме­нять к этим груп­пам ог­раничения на ре­сур­сы. Systemd поль­зу­ет­ся этой функ­ци­ей груп­пи­ров­ки, и ему тре­бу­ет­ся ак­ти­ва­ция CONFIG_CGROUPS в кон­фи­гу­ра­ции яд­ра (она не ис­поль­зу­ет ог­раничение ре­сур­сов cgroup и не тре­бу­ет ак­ти­ва­ции этих до­полнитель­ных па­ра­мет­ров яд­ра). Мож­но уви­деть ор­ганиза­цию, обес­пе­чи­ваю­щую ис­поль­зо­вание кон­троль­ных групп:

$ systemd-cgls

или про­смот­реть пред­став­ле­ние cgroup с по­мо­щью ко­ман­ды ps:

$ ps xawf -eo pid,user,cgroup,args

Еще од­но важ­ное из­менение, при­шед­шее с systemd, со­сто­ит в том, что он пре­достав­ля­ет свои соб­ст­вен­ные сред­ст­ва ве­дения ло­гов, ко­то­рый она на­зы­ва­ет жур­нал [journal]. Жур­нал мо­жет за­менить тра­ди­ци­он­ный syslog (но они мо­гут и со­су­ще­ст­во­вать). Systemd ис­поль­зу­ет служ­бу systemd.journald вме­сто от­дель­но­го объ­ек­та syslog вро­де syslog-ng.

Ос­нов­ное раз­ли­чие ме­ж­ду journal и тра­ди­ци­он­ным сис­тем­ным жур­на­лом яв­ля­ет­ся то, что journal – это дво­ич­ная ба­за дан­ных, тогда как сис­тем­ный лог за­пи­сы­ва­ет­ся в тек­сто­вый файл в /var/log. Это оз­на­ча­ет, что для чтения жур­на­ла нуж­ны осо­бые сред­ст­ва, но они до­воль­но про­сты: ко­ман­да journalctl, ис­поль­зо­ван­ная са­ма по се­бе, пе­ре­чис­лит все жур­на­лы. Вме­сте с тем, по­лез­ные ре­зуль­та­ты мож­но по­лу­чить с по­мо­щью фильт­ров:

$ journalctl /usr/bin/sshd

или по име­ни мо­ду­ля:

$ journalctl _SYSTEMD_UNIT=sshd.service

По умол­чанию, journal неста­би­лен: он за­пи­сы­ва­ет­ся на вре­мен­ное хранение в /run/log/journal, ес­ли толь­ко не су­ще­ст­ву­ет ка­та­лог /var/log/journal. Соз­дав та­кой ка­та­лог, мож­но сде­лать journal по­сто­ян­ным. Раз­ные ва­ри­ан­ты на­строй­ки для управ­ления по­ве­дением journal ука­зы­ва­ют­ся в фай­ле /etc/systemd/journald.conf.

Journal – не про­сто за­ме­на сис­тем­но­го жур­на­ла: он так­же со­би­ра­ет со­об­щения яд­ра, дис­ка в опе­ра­тив­ной па­мя­ти для на­чаль­ной инициа­ли­за­ции, ранних со­об­щений за­груз­ки, а так­же со­об­щения, за­пи­сан­ные в стан­дарт­ный вы­вод об ошиб­ках всех служб. journal мож­но так­же ис­поль­зо­вать вме­сто та­ких средств, как dmesg, что­бы про­смот­реть со­об­щения яд­ра, на­при­мер:

$ journalctl _TRANSPORT=kernel

Раз­ные ва­ри­ан­ты досту­па к ре­ги­ст­ра­ци­он­ным дан­ным ука­за­ны в man journalctl. Systemd так­же пре­достав­ля­ет ин­ст­ру­мен­ты для ана­ли­за ин­фор­ма­ции, ко­то­рую он со­би­ра­ет. Мож­но про­ве­рить вре­мя за­груз­ки сис­те­мы:

$ systemd-analyze

Startup finished in 4475ms (kernel) + 100491ms (userspace) = 104966ms

[За­пуск за­вер­шен за 4475 мс (яд­ро) + 100491 мс (поль­зо­ва­тель­ское про­стран­ст­во) = 104966 мс]

Этот вы­вод по­ка­зы­ва­ет вре­мя за­груз­ки по час­тям, в яд­ре и в поль­зо­ва­тель­ском про­стран­ст­ве. Ес­ли за­груз­ка про­хо­дит не так бы­ст­ро, как хо­те­лось бы, вы здесь уви­ди­те, чья это ви­на:

$ systemd-analyze blame

$ systemd-analyze plot > plot.svg

Две фор­мы вы­во­да дан­ных – на тер­ми­нал и в ви­де гра­фи­ка. Тре­тья фор­ма вы­во­да – гра­фик за­ви­си­мо­стей. Он вы­во­дит дан­ные в фор­ма­те dot то­чек для дальней­шей об­ра­бот­ки в GraphViz (от­кры­тое ПО для ви­зуа­ли­за­ции гра­фов). Ес­ли па­кет GraphViz уста­нов­лен, вы мо­же­те соз­да­вать гра­фи­че­­ские фай­лы SVG:

$ systemctl dot | dot -Tsvg > systemd.svg

По­лу­чен­ный гра­фик по­ка­зы­ва­ет упо­ря­до­чен­ное рас­по­ло­жение и тре­бо­вания за­ви­си­мо­стей; в сы­ром ви­де он мо­жет быть до­воль­но ве­лик, но вы­вод мож­но ог­раничить кон­крет­ны­ми за­ви­си­мо­стя­ми. Ис­поль­зо­вание жур­на­ла и этих ин­ст­ру­мен­тов ана­ли­за по­зво­ля­ет лег­че уста­но­вить при­чи­ну за­дер­жек в про­цес­се за­груз­ки.

Но­вый вид chroot

Systemd вклю­ча­ет два но­вых ме­ханиз­ма, аль­тер­на­тив­ных ис­поль­зо­ванию chroot. Пер­вый – под­держ­ка про­странств имен фай­ло­вой сис­те­мы, от­но­си­тель­но но­вая функ­ция яд­ра. Они пре­достав­ля­ют бо­лее мощ­ную аль­тер­на­ти­ву ис­поль­зо­ванию chroot для ог­раничения сфе­ры дей­ст­вия служ­бы. Вы мо­же­те сде­лать ка­та­ло­ги доступ­ны­ми толь­ко для чтения или пол­но­стью недоступ­ны­ми для ка­кой-ли­бо служ­бы. В раз­дел [Service] фай­ла кон­фи­гу­ра­ции юнита служ­бы мо­гут быть до­бав­ле­ны две ди­рек­ти­вы: ReadOnlyDirectories мо­жет быть ис­поль­зо­ва­на для пе­ре­чис­ления ка­та­ло­гов, ко­то­рые служ­ба мо­жет толь­ко чи­тать, а InaccessibleDirectories сде­ла­ет ка­та­ло­ги неви­ди­мы­ми для служ­бы.

На­при­мер, что­бы не по­зво­лить служ­бе трогать ваш до­машний ка­та­лог /home, до­бавь­те ди­рек­ти­ву в ее файл на­строй­ки:

[Service]

InaccessibleDirectories=/home

По­сле это­го служ­ба не уви­дит до­машний ка­та­лог /home и бу­дет счи­тать, что его нет.

Вто­рой ме­ханизм, обес­пе­чи­вае­мый systemd, на­зы­ва­ет­ся systemd-nspawn и по­зво­ля­ет за­пускать госте­вую ОС внут­ри кон­тейнера. Он на­хо­дит­ся ме­ж­ду chroot и Linux Containers. Это бо­лее мощ­ное и безо­пас­ное сред­ст­во, чем chroot: оно вир­туа­ли­зи­ру­ет ие­рар­хию фай­ло­вой сис­те­мы, де­ре­во про­цес­сов, под­сис­те­мы IPC, а так­же хост и до­мен­ное имя. Од­на­ко оно, хо­тя и ис­поль­зу­ет те же ба­зо­вые тех­но­ло­гии яд­ра, не яв­ля­ет­ся пол­но­цен­ным кон­тейнер­ным ре­шением, та­ким как Linux Containers – на­при­мер, оно не обес­пе­чи­ва­ет вир­туа­ли­за­цию се­ти. Зато соз­дать кон­тейнер systemd-nspawn очень про­сто.

Соз­дать и за­гру­зить госте­вую ОС на Arch Linux мож­но дву­мя про­сты­ми ко­ман­да­ми:

$ mkarchroot base arch-container

$ systemd-nspawn -D arch-container/ /sbin/init

Это по­зво­лит за­гру­зить кон­тейнер в под­сказ­ку для вхо­да в сис­те­му. Для кон­тейнеров на осно­ве Debian мож­но ис­поль­зо­вать debootstrap.

При ис­поль­зо­вании кон­тейнеров иногда по­лез­но знать, что вы на­хо­ди­тесь в од­ном из них. Systemd по­мо­жет и здесь: ко­ман­да systemd-detect-virt со­об­щит вам, ра­бо­тае­те ли вы в вир­туа­ли­зи­ро­ван­ной сре­де. Она вернет “none” или имя ис­поль­зуе­мой сре­ды:

$ systemd-detect-virt lxc

systemd-detect-virt мо­жет об­на­ру­жить qemu, kvm, vmware, microsoft, oracle, xen, bochs, chroot, openvz, lxc, lxc-libvirt и systemd-nspawn. Ис­поль­зуя systemd, вы мо­же­те изо­ли­ро­вать служ­бу от се­ти, за­дать ей соб­ст­вен­ный ка­та­лог /tmp или уда­лить из него функ­цио­наль­ные воз­мож­но­сти. Вы так­же мо­же­те при­менить ог­раничения ре­сур­сов cgroup. Для по­лу­чения до­полнитель­ной ин­фор­ма­ции об этих по­лез­ных до­полнениях об­ра­ти­тесь к спра­воч­ной странице systemd.exec.

На нашем уро­ке мы рас­смот­ре­ли доста­точ­но воз­мож­но­стей systemd, что­бы дать вам хо­ро­шее пред­став­ление о том, как его на­стро­ить и как он ра­бо­та­ет. Их го­раз­до боль­ше, чем ре­аль­но бы­ло бы рас­смот­реть в столь ко­рот­кой ста­тье, но все это очень хо­ро­шо до­ку­мен­ти­ро­ва­но, и когда это бу­дет при­менено в ва­шем лю­би­мом ди­ст­ри­бу­ти­ве, вы бу­де­те го­то­вы. |

Персональные инструменты
купить
подписаться
Яндекс.Метрика