В лучших традициях блоггинга, выношу из личной переписки то, что рассказываю уже не в первый раз — теперь буду просто ссылаться сюда.
Как вы, наверное, знаете, в *nix, в отличие от Windows, можно удалить открытый кем-то файл, при этом имя из файловой системы пропадает сразу, а место, занятое данными, освободится лишь после закрытия файла всеми процессами.
При обновлении системы ситуацию с уже удалёнными, но всё ещё кем-то используемыми файлами можно встретить сплошь и рядом: при обновлении библиотеки старый .so
может быть удалён, а на его место под тем же именем помещена новая сборка. При этом процессы, использующие старую версию, будут продолжать ею пользоваться, а новые будут запускаться уже с обновлённой. Это может привести к проблемам: к примеру, в случае с Heartbleed одного только обновления libssl
мало, нужно ещё и перезапустить sshd
, Nginx, Apache и вообще всё-всё-всё, что работало с SSL.
В Debian есть готовое решение, работающее с любым демоном — checkrestart
(пакет debian-goodies
). Он показывает, какие из демонов пользуются устаревшими файлами, и объясняет, как их перезапустить.
Однострочник, которым я пользуюсь, чуть более примитивен и при этом немного более универсален: он смотрит на все без исключения процессы, не разбираясь, демон это или нет:
$ sudo lsof / | grep DEL | cut -f1 -d' ' | sort -u
Что он делает:
-
lsof
показывает все-все-все открытые файлы и сокеты. lsof /
показывает только файлы. При запущенном торрент-клиенте, постоянно плодящем соединения, вывод сокетов занимает кучу времени, поэтому я отсеиваю их на этом этапе;
-
в выводе lsof
присутствует колонка TYPE
, показывающая тип открытого ресурса: файл (REG
), директория (DIR
), сокет (IPv4
или IPv6
) и, наконец, файлы, которые были удалены (DEL
). Есть ещё целая куча других типов, читайте lsof(8). В общем, grep DEL
выдирает строки с удалёнными файлами;
-
в получившемся списке меня интересуют только имена процессов (первая колонка), поэтому я вырезаю её (cut
) и сортирую, удаляя повторяющиеся строки (sort -u
);
-
voilà: теперь у нас есть список процессов, которые нужно перезапустить. Эту часть я всё никак не соберусь автоматизировать.
Некоторые процессы могут перезапускаться не самостоятельно, а вместе с другими, например:
- для перезапуска
udisksd
, polkitd
и console-kit
нужно перезапустить dbus
;
- для перезапуска
dhclient
и wicd-monitor
нужно убить dhclient
(sudo pkill dhclient
), перезапустить wicd
и, кажется, переподключиться к сети.
Некоторые другие процессы перезапустить вообще нельзя (например, systemd
— там хоть и есть daemon-reexec
, но у меня он почему-то никогда не работает).
И, конечно же, не следует забывать про ядро — в списке процессов его не видно, но обновления придти могут. Тут уже только ребут поможет (или ksplice, но ребутнуться проще :).
http://debiania.in.ua/posts/2014-08-29-checking-for-processes-to-restart.html