Материал подготовлен командой Simple-Server для администраторов VPS и выделенных серверов. Команды и пути проверяйте на тестовой машине перед production.
Кратко о задаче
Перед работой с командой сперва необходимо проверить версию установленного nohup:
Можно также использовать короткий способ записи:
Если nohup присутствует в системе, в консоли появится примерно такой вывод:
nohup (GNU coreutils) 8.32
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Jim Meyering.Как видно, в этом руководстве используется nohup версии 8.32, которая работает на операционной системе Ubuntu 22.04.
Кстати, системную справку о команде можно получить так:
Дополнительно можно просмотреть полноценную документацию в формате Texinfo прямо в терминале консоли:
Давайте запустим простой процесс, выводящий состояние текущего каталога, через nohup:
В консоли появится информирующее (то есть не являющееся ошибкой) сообщение о том, что вывод указанной команды будет перенаправлен в файл nohup.out:
nohup: ignoring input and appending output to 'nohup.out'Давайте удостоверимся, что это действительно так:
В консоли появится список существующих файлов и каталогов:
nohup.out resize.log snapТеперь выведем содержимое нового файла:
В консоли появится следующий список:
nohup.out
resize.log
snapОбратите внимание, что файл nohup.out был создан перед выполнением команды ls. В противном случае сохраненный консольный вывод был бы таким:
В созданный файл автоматически записываются выходные данные двух стандартных потоков:
-
stdout— стандартный поток вывода. -
stderr— стандартный поток ошибок.
stdout — стандартный поток вывода.
stderr — стандартный поток ошибок.
В этом примере команда ls выполняется однократно — нет никакого смысла запускать ее через nohup. Поэтому имеет смысл рассмотреть запуск процесса, выполнение которого будет достаточно продолжительным, чтобы успеть выйти из консольного терминала и вернуться обратно.
Например, мы могли бы сымитировать долгое выполнение команды с помощью собственного shell-скрипта, представляющего собой обычный таймер.
Внутри будет цикл, ведущий обратный отсчет каждую секунду:
#!/bin/sh
i=10
while [ "$i" -gt 0 ]; do
echo "$i"
sleep 1
i=$(( i - 1 ))
doneТакже важно не забыть сделать созданный скрипт исполняемым файлом, чтобы не было ошибки при запуске:
Теперь запустим скрипт, чтобы протестировать его работу:
В терминале консоли каждую секунду начнут появляться числа от 10 до 1. Общий вывод будет таким:
Чтобы в дальнейшем не было путаницы, удалим ранее созданные файлы с выводами:
Теперь можно запустить созданный скрипт через nohup:
Как только начнется обратный отсчет, можно закрыть консольный терминал и вернуться в него уже через 10 секунд, выполнив переподключение к удаленному серверу через SSH.
Далее посмотрим содержимое файла с выводом:
Внутри будет все та же последовательность чисел:
Таким образом, запущенный процесс продолжал обратный отсчет даже после отключения пользователя от терминала консоли.
Запуск процесса в фоновом режиме
С помощью nohup продолжительно выполняющийся процесс можно запустить в фоновом режиме. Это означает, что он будет активен и когда мы будем выполнять другие команды, и когда мы выйдем из консольного терминала, и когда мы в него вернемся.
Для примера можно запустить утилиту диагностики сети ping, которая будет регулярно отправлять запрос на сайт Simple-Server.
Давайте сперва протестируем отправку запроса без nohup:
В консоли появится следующий вывод:
PING simple-server.tech (178.248.239.157) 56(84) bytes of data.
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=1 ttl=58 time=7.94 msПри этом последняя строчка будет продолжать выводиться в терминал каждую секунду, информируя о результате очередного запроса:
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=2 ttl=58 time=7.62 ms
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=3 ttl=58 time=7.61 ms
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=4 ttl=58 time=7.64 ms
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=5 ttl=58 time=7.59 msЗаранее очистим файл с консольными выводами:
Для запуска процесса в фоновом режиме через nohup после аргументов команды нужно указать символ амперсанда:
nohup ping simple-server.tech &В консоли появится следующий вывод:
[1] 29649
root@3494829-yn55665:~# nohup: ignoring input and appending output to 'nohup.out'Набор цифр в начале является идентификатором запущенного процесса.
Теперь можно выйти из консольного терминала и снова в него зайти.
Чтобы убедиться в том, что запущенный процесс до сих пор активен, нужно запросить список рабочих процессов:
В консоли появится строка с идентификатором, именем и аргументом запущенного процесса:
Впоследствии с помощью этого идентификатора процесс можно будет остановить.
Кстати, для просмотра запущенных процессов можно воспользоваться другой командой:
Фактически тут используется конвейер из двух команд:
-
ps aux— выводит список всех процессов. -
grep ping— находит в списке из вывода строку с ключевым словом «ping».
ps aux — выводит список всех процессов.
grep ping — находит в списке из вывода строку с ключевым словом «ping».
В консоли появится примерно такой вывод:
root 29649 0.0 0.1 7720 1264 pts/0 S 23:10 0:00 ping simple-server.tech
root 29656 0.0 0.2 6480 2228 pts/0 S+ 23:10 0:00 grep --color=auto pingВ данном случае первая строчка — искомый процесс.
Кстати, можно смотреть за записью вывода в файл в режиме реального времени:
Команда tail выводит последние строки указанного файла, а дополнительный флаг -f позволяет делать вывод в режиме реального времени в момент дополнения файла другими процессами.
Поэтому в консоли появятся строки с результатами удаленных запросов, которые будут дополняться новым выводом запущенного процесса:
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=344 ttl=58 time=7.60 ms
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=345 ttl=58 time=7.56 ms
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=346 ttl=58 time=7.59 ms
...
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=354 ttl=58 time=7.62 msФактически таким образом можно записывать консольный вывод в произвольный файл и одновременно показывать его в терминале.
Чтобы остановить запущенный процесс, нужно указать его идентификатор:
Теперь, если проверить список активных процессов, вывод будет пуст:
Либо можно снова воспользоваться другим способом поиска процессов:
Тогда в выводе будет содержаться только процесс grep, который запускается для целей поиска:
root 30172 0.0 0.2 6480 2360 pts/0 S+ 23:13 0:00 grep --color=auto pingТеперь, можно взглянуть на сохраненный в файле консольный вывод.
Вывод будет примерно таким:
PING simple-server.tech (178.248.239.157) 56(84) bytes of data.
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=1 ttl=58 time=10.9 ms
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=2 ttl=58 time=7.65 ms
...
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=17 ttl=58 time=7.70 msТаким образом, запущенный процесс продолжает работать и записывать вывод в отдельный файл вне зависимости от активности консольного терминала.
Запуск нескольких процессов в фоновом режиме
Помимо прочего, через nohup можно выполнять несколько команд в фоновом режиме.
Давайте сперва очистим ранее сохраненный вывод:
А потом запустим сразу 2 процесса в фоновом режиме:
nohup bash -c './timer.sh && ping simple-server.tech' &Обратите внимание, что в конце команды аналогично стоит знак амперсанда.
В этом примере у нас сперва отработает таймер (на это уйдет 10 секунд), после чего начнется регулярный цикл отправки удаленных запросов.
Поэтому, подождав около 15 секунд (в это время можно также попробовать закрыть и снова открыть терминал консоли), выведем файл с сохраненным консольным выводом:
Содержимое внутри будет примерно таким:
10
9
8
7
6
5
4
3
2
1
PING simple-server.tech (178.248.239.157) 56(84) bytes of data.
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=1 ttl=58 time=7.90 ms
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=2 ttl=58 time=7.68 ms
...
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=7 ttl=58 time=7.67 msТо есть внутри файла nohup.out находится комбинируемый последовательный вывод — сначала отсчет таймера, потом череда удаленных запросов. Таким образом, указанные команды запускаются последовательно.
Поэтому точно так же можно запустить три и более команд:
nohup bash -c './timer.sh && ./timer.sh && ping simple-server.tech' &В этоv случае новый записанный вывод будет примерно таким:
10
9
8
7
6
5
4
3
2
1
10
9
8
7
6
5
4
3
2
1
PING simple-server.tech (178.248.239.157) 56(84) bytes of data.
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=1 ttl=58 time=7.34 ms
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=2 ttl=58 time=7.56 ms
...
64 bytes from 178.248.239.157 (178.248.239.157): icmp_seq=7 ttl=58 time=7.24 msПо умолчанию команда nohup записывает вывод в файл nohup.out. Тем не менее, при запуске процесса можно в явном виде указать файл для перенаправления вывода с помощью знака перенаправления:
nohup ./timer.sh > myout1В консоли появится сообщение о перенаправлении потока ошибок и вывода:
nohup: ignoring input and redirecting stderr to stdoutПроверим состояние файловой системы:
Как видно, появился ранее указанный файл:
myout1 nohup.out resize.log snapТеперь посмотрим его содержимое:
Как видно, оно аналогично всем предыдущим выводам:
Схожим образом работает перенаправление вывода для процессов в фоновом режиме:
nohup ./timer.sh > myout1 &Обратите внимание, что амперсанд указывается после перенаправления вывода.
Процесс таймера будет автоматически уничтожаться после завершения таймера — вручную ничего останавливать не надо.
А теперь давайте посмотрим на поведение команды nohup при указании амперсанда перед перенаправлением.
Сперва удалим все существующие файлы с консольным выводом:
rm myout1 && rm nohup.outИ выполним такую команду:
nohup ./timer.sh & > myout1В консоли появится стандартный вывод, сообщающий о создании фонового процесса.
Проверим состояние файловой системы:
Как видно, у нас появились два новых файла — myout1 и nohup.out:
myout1 nohup.out resize.log snap timer.shТем не менее, запись будет выполняться только в nohup.out, а файл myout1 создался исключительно потому, что было явно указано перенаправление.
Содержимое myout1 будет пустым:
А вот если проверить nohup.out:
То внутри него окажется привычный вывод отсчета таймера:
Поэтому важно всегда указывать символ амперсанда (&) в конце каждой командной строки, если требуется запускать процесс в фоновом режиме.
Также не забывайте контролировать активные процессы — не допускайте их дублирования, завершайте лишние и прорабатывайте механизмы автоматической остановки запущенных программ.
Это позволит избежать утечек вычислительных ресурсов и повысить безопасность разворачиваемых инфраструктур.
Может возникнуть закономерный вопрос: чем nohup отличается от классического демона в Linux? На первый взгляд может показаться, что это одно и то же.
Особенность демонов в том, что они постоянно работают в фоновом режиме. Очень продолжительное время. Неделями и месяцами. По сути, всегда. Например, это могут быть HTTP-серверы или базы данных. Устройство процессов-демонов всегда сложнее — это не одноразовые скрипты.
Напротив, nohup предназначен для одноразового использования. Обычно это некий сценарий, который выполняется продолжительно (минуты или часы), но все равно завершается.
Например, это может быть процесс, сортирующий какие-то данные, или выполняющий последовательность удаленных запросов. Такие задачи однократны, но занимают время — было бы неудобно оставлять терминал открытым.
То есть с помощью nohup можно выполнять несколько долгих задач в фоновом режиме, занимаясь в это время другими делами.
Команда nohup — это не про запуск бесконечных демонов. Это про однократные, но долгие задачи.
Нужен сервер для практики? Арендуйте VPS/VDS в России — root-доступ, NVMe, DDoS-защита и поддержка 24/7.