Как запустить процесс в Linux

Обновлено: 21.11.2024

В этом руководстве мы рассмотрим простую, но важную концепцию обработки процессов в системе Linux, а именно, как полностью отсоединить процесс от управляющего им терминала.

Когда процесс связан с терминалом, могут возникнуть две проблемы:

  1. ваш управляющий терминал заполнен огромным количеством выходных данных и сообщений об ошибках/диагностике.
  2. в случае закрытия терминала процесс вместе с его дочерними процессами будет завершен.

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

Как запустить процесс или команду Linux в фоновом режиме

Если процесс уже выполняется, как в приведенном ниже примере команды tar, просто нажмите Ctrl+Z, чтобы остановить его, затем введите команду bg, чтобы продолжить его выполнение в фоновом режиме в качестве задания.

Вы можете просмотреть все свои фоновые задания, введя jobs . Однако его stdin, stdout, stderr по-прежнему подключены к терминалу.

Вы также можете запустить процесс прямо из фона, используя амперсанд и знак &.

Взгляните на приведенный ниже пример, хотя команда tar была запущена как фоновое задание, на терминал все равно было отправлено сообщение об ошибке, означающее, что процесс все еще подключен к управляющему терминалу.

Оставить процессы Linux запущенными после выхода из терминала

Мы будем использовать команду disown, она используется после того, как процесс был запущен и переведен в фоновый режим, его работа заключается в удалении задания оболочки из списка активных заданий оболочки, поэтому вы не будете использовать команды fg , bg для этой конкретной работы больше.

Кроме того, когда вы закрываете управляющий терминал, задание не зависает и не отправляет SIGHUP каким-либо дочерним заданиям.

Давайте рассмотрим приведенный ниже пример использования встроенной функции diswon bash.

Вы также можете использовать команду nohup, которая также позволяет процессу продолжать работу в фоновом режиме, когда пользователь выходит из оболочки.

Отключить процессы Linux от управляющего терминала

Поэтому, чтобы полностью отсоединить процесс от управляющего терминала, используйте приведенный ниже формат команды, он более эффективен для приложений с графическим интерфейсом пользователя (GUI), таких как Firefox:

В Linux /dev/null — это специальный файл устройства, который списывает (удаляет) все записанные в него данные. В приведенной выше команде ввод считывается, а вывод отправляется в /dev/null.

В качестве заключительного замечания: при условии, что процесс подключен к управляющему терминалу, как пользователь, вы увидите несколько выходных строк данных процесса, а также сообщения об ошибках на своем терминале. Опять же, когда вы закроете управляющий терминал, ваш процесс и дочерние процессы будут завершены.

Важно, чтобы с любыми вопросами или замечаниями по теме, свяжитесь с нами, используя форму комментариев ниже.

Если вам понравилась эта статья, подпишитесь на уведомления по электронной почте о руководствах по Linux. Если у вас есть вопросы или сомнения? обратитесь за помощью в разделе комментариев.

Если вы цените то, что мы делаем здесь, в TecMint, вам следует подумать о следующем:

TecMint – это самый быстрорастущий и пользующийся наибольшим доверием сайт сообщества, где можно найти любые статьи, руководства и книги по Linux в Интернете. Миллионы людей посещают TecMint! для поиска или просмотра тысяч опубликованных статей, доступных всем БЕСПЛАТНО.

Если вам нравится то, что вы читаете, купите нам кофе (или 2) в знак признательности.

Мы благодарны за вашу бесконечную поддержку.

Похожие сообщения

9 мыслей о «Как запустить команду Linux в фоновом режиме и отсоединить процесс в терминале»

Небольшое улучшение:

Без "disown" вы получите следующий вывод в исходном терминале после закрытия данной программы:

«[1]+ Готово Firefox /dev/null»

Это происходит только в следующий раз, когда что-то выводится в выходной поток терминала. Таким образом, при следующем запуске команды выполняется запись в выходной поток.

Чтобы проверить это, запустите его без "disown", закройте Firefox и запустите "ls".

Я вижу, что это старый пост, но я думаю, что мой вопрос находится на приблизительном уровне. то, что я хотел бы сделать, это открыть консоль процесса, который был запущен с помощью systemd с флагом без графического интерфейса. что это относится к серверу Minecraft.

поэтому я создал служебный файл systemd, а команда выполнения — «java -jar server.jar nogui». Теперь, когда система запущена и работает, я хотел бы открыть графический интерфейс или консоль сервера Minecraft, чтобы выполнять команды без вам нужно открыть программу запуска Minecraft, как если бы вы играли в игру. Я знаю, что делал что-то подобное в прошлом на других платформах, но я просто недостаточно знаю о Minecraft/java, чтобы это произошло.

Я использую Ubuntu 18.04, а текущая версия Minecraft — 1.15.2

Как просмотреть задания, запущенные в предыдущем сеансе? Я отправил задания в nohup и вышел из системы. После повторного входа в систему, если я хочу увидеть задания, и если я хочу убить, как это сделать

Или вы можете сделать что-то простое, например:

Выйдите из терминала или сеанса ssh, и он продолжит работу

Отлично, спасибо, что поделились этим.

Я запускаю скрипт, который копирует файлы с одного сервера на 3 других сервера. Вывод, который я получаю, - это предупреждение от других серверов, когда я делаю ssh, даже когда я запускаю скрипт с & в конце или если я перемещаю его в фоновом режиме с помощью ^Z и bg. Итак, мой вопрос: не могли бы вы дать мне несколько советов, как я могу предотвратить отображение этого вывода. Заранее спасибо.

С уважением,
Владимир Тодоров

Это было очень полезно! Спасибо большое.
Я всегда использовал 2-3 терминала для одновременного запуска разных приложений, таких как Android Studio, ract-native, node, webstorm и т. д.
Эти команды помогли мне иметь только один терминал, когда все они работают в фоновом режиме.

Есть что сказать? Присоединяйтесь к обсуждению. Отменить ответ

Этот сайт использует Akismet для уменьшения количества спама. Узнайте, как обрабатываются данные ваших комментариев.

Предположим, вы впервые изучаете командную строку Linux или входите в администрирование Linux. В этом случае важно иметь низкоуровневое понимание того, как обойти терминал и выполнить основные задачи. Чтобы помочь вам понять эти концепции, ознакомьтесь с двумя моими предыдущими статьями:

Однако, если вы чувствуете себя комфортно с этими концепциями, мы немного расширим ваши знания о Linux в этой статье. Мы рассмотрим процессы и способы управления ими.

Итак, что такое процесс?

Дополнительные ресурсы по Linux

В Linux процесс — это любой активный (работающий) экземпляр программы. Но что такое программа? Ну, технически программа — это любой исполняемый файл, хранящийся в памяти на вашем компьютере. Каждый раз, когда вы запускаете программу, вы создаете процесс. На базовом уровне этим довольно легко управлять, и именно это мы и рассмотрим сегодня.

Что нужно для начала

Я рекомендую вам использовать вашу любимую виртуальную машину. Таким образом, вы можете попробовать и потерпеть неудачу без каких-либо последствий (что, безусловно, лучший способ чувствовать себя комфортно за терминалом).

Для этой демонстрации я собираюсь запустить процесс сна на 500 секунд.Такой подход позволяет вам наблюдать за процессом, не внося существенных изменений в мою систему.

Затем я остановил процесс с помощью Ctrl+Z, чтобы мы могли использовать наш терминал.

1. Список процессов

Чтобы отобразить текущие активные процессы, используйте команду ps:

Здесь вы получите небольшую информацию об активных процессах в вашей системе. Обратите внимание на PID (уникальный идентификатор процесса), TIME (количество времени, в течение которого процесс выполнялся) и CMD (команда, выполняемая для запуска процесса).

2. Подробный список (процессов)

Чтобы просмотреть невероятно подробный список процессов, вы можете использовать команду ps aux.

  • а — все пользователи
  • u — показывает пользователя/владельца
  • x - отображает процессы, не запущенные в терминале (что делает вывод довольно длинным)

Вы можете увидеть команду здесь (длина вывода изменена):

3. Убить по PID

Неизбежно процесс зависнет, и вам нужно будет его убить. Чем больше времени вы проводите в CLI, тем больше вероятность того, что вам понадобится команда kill. Самый точный способ идентифицировать процесс — по идентификатору процесса (PID).

Используйте следующий синтаксис:

Эта команда отправляет сигнал SIGTERM. Однако, если вы имеете дело с зависшим процессом, добавьте параметр -9.

4. Убить по имени/ключевому слову

Используйте команду killall, чтобы убить процесс по имени. Эта команда уничтожит все процессы с указанным вами ключевым словом/именем.

Это уничтожит все спящие процессы, активные в системе (здесь также работает параметр -9). Вот пример:

Следующие две команды идут рука об руку. Они позволяют перемещать/управлять фоновыми командами. Я дам базовый взгляд на синтаксис ниже; однако подробное описание этих команд см. в моей предыдущей статье на эту тему.

5. Список фоновых заданий и возобновление фоновых заданий

Чтобы получить список фоновых заданий и управлять ими, мы будем использовать команду bg. Я запустил новый процесс sleep 500, а затем остановил его, отправив в фоновый режим. Таким образом, мы видим его в списке при запуске bg ниже:

6. Вывести самое последнее задание на передний план

Для этого воспользуемся командой fg. Это выводит последнее запущенное задание/процесс на передний план. Следующий пример является продолжением приведенной выше команды. Процесс сна 500, который находился в фоновом режиме, теперь активен в фоновом режиме. Давайте вынесем это на свет.

Эта команда подводит нас к последней команде в этом списке.

7. Вывести конкретную работу на передний план

Снова используйте команду fg, но выберите конкретное задание, которое нужно вывести на передний план (вместо самого последнего). Для этого мы просто добавим в команду имя задания/процесса.

Это выводит задание XXXample на передний план.

[ Хотите проверить свои навыки системного администратора? Пройдите оценку навыков сегодня. ]

Как правило, жизненный цикл процесса приложения имеет три основных состояния: запуск, выполнение и остановка. Каждое состояние можно и нужно тщательно контролировать, если мы хотим быть компетентными администраторами. Эти восемь команд можно использовать для управления процессами на протяжении их жизненного цикла.

Запуск процесса

Самый простой способ запустить процесс — ввести его имя в командной строке и нажать Enter. Если вы хотите запустить веб-сервер Nginx, введите nginx. Возможно, вы просто хотите проверить версию.

Просмотр пути к исполняемому файлу

Приведенная выше демонстрация запуска процесса предполагает, что исполняемый файл находится в пути к исполняемому файлу. Понимание этого пути является ключом к надежному запуску процесса и управлению им. Администраторы часто настраивают этот путь для своих целей. Вы можете просмотреть путь к исполняемому файлу, используя команду echo $PATH.

КАКОЙ

Используйте команду which для просмотра полного пути к исполняемому файлу.

Для своих примеров я буду использовать популярное программное обеспечение веб-сервера Nginx. Предположим, что Nginx установлен. Если команда, которую nginx ничего не возвращает, значит, Nginx не найден, потому что ищет только указанный вами путь к исполняемому файлу. Есть три способа исправить ситуацию, когда процесс не может быть запущен просто по имени. Первый — ввести полный путь. Хотя я бы предпочел не печатать все это, а вы?

Терминал Linux

Вторым решением может быть установка приложения в каталог по пути к исполняемому файлу. Однако это может быть невозможно, особенно если у вас нет привилегий root.

Третье решение – обновить переменную среды пути к исполняемому файлу, включив в нее каталог, в котором установлено конкретное приложение, которое вы хотите использовать. Это решение зависит от оболочки. Например, пользователям Bash потребуется отредактировать строку PATH= в своем файле .bashrc.

Теперь повторите свое эхо и какие команды или попробуйте проверить версию. Гораздо проще!

Поддержание процесса в рабочем состоянии

НОХУП

Процесс может прерваться, если вы выйдете из системы или закроете терминал. Этого особого случая можно избежать, если перед командой, которую вы хотите запустить, поставить команду nohup. Кроме того, добавление амперсанда (&) переводит процесс в фоновый режим и позволяет продолжить работу с терминалом. Например, предположим, что вы хотите запустить myprogram.sh.

Одна приятная вещь, которую делает nohup, — это возврат PID запущенного процесса. Далее я расскажу подробнее о PID.

Управление запущенным процессом

Терминал Linux

Каждому процессу присваивается уникальный идентификационный номер процесса (PID). Это число используется для управления каждым процессом. Мы также можем использовать имя процесса, как я продемонстрирую ниже. Есть несколько команд, которые могут проверить состояние запущенного процесса. Давайте кратко рассмотрим их.

Наиболее распространенным является ps. Вывод ps по умолчанию — это простой список процессов, запущенных в вашем текущем терминале. Как вы можете видеть ниже, первый столбец содержит PID.

Я хочу просмотреть процесс Nginx, который я запустил ранее. Для этого я говорю ps показать мне каждый запущенный процесс (-e) и полный список (-f).

Вы можете увидеть процессы Nginx в выводе команды ps выше. Команда отображала почти 300 строк, но я сократил ее для этой иллюстрации. Как вы можете себе представить, попытка обработать 300 строк информации о процессе немного запутала. Мы можем направить этот вывод в grep, чтобы отфильтровать nginx.

Так лучше. Мы можем быстро увидеть, что Nginx имеет PID 20520 и 20521.

PGREP

Команда pgrep была создана для дальнейшего упрощения за счет устранения необходимости вызывать grep отдельно.

Предположим, вы находитесь в среде хостинга, где несколько пользователей запускают несколько разных экземпляров Nginx. Вы можете исключить других из вывода с помощью параметра -u.

ПИДОФ

Еще один отличный вариант — pidof. Эта команда проверит PID определенного двоичного файла, даже если запущен другой процесс с таким же именем. Чтобы настроить пример, я скопировал свой Nginx во второй каталог и запустил его с соответствующим набором префиксов. В реальной жизни этот экземпляр может находиться в другом месте, например в каталоге, принадлежащем другому пользователю. Если я запускаю оба экземпляра Nginx, вывод ps -ef показывает все их процессы.

Использование grep или pgrep покажет номера PID, но мы не сможем различить, какой экземпляр является каким.

Команду pidof можно использовать для определения PID каждого конкретного экземпляра Nginx.

Команда top существует уже давно и очень полезна для просмотра сведений о запущенных процессах и быстрого выявления таких проблем, как нехватка памяти. Его вид по умолчанию показан ниже.

Интервал обновления можно изменить, введя букву s и желаемое количество секунд для обновлений. Чтобы упростить мониторинг нашего примера процессов Nginx, мы можем вызвать top и передать PID с помощью параметра -p. Этот вывод намного чище.

Важно правильно определить PID при управлении процессами, особенно при их остановке. Кроме того, при таком использовании top каждый раз, когда один из этих процессов останавливается или запускается новый, необходимо будет информировать top о новых процессах.

Остановка процесса

Интересно, что нет команды остановки. В Linux есть команда kill. Kill используется для отправки сигнала процессу. Чаще всего используется сигнал «завершить» (SIGTERM) или «убить» (SIGKILL). Однако их гораздо больше. Ниже приведены некоторые примеры. Полный список можно просмотреть с помощью команды kill -L.

Сигнал уведомления номер девять — SIGKILL. Обычно мы выдаем такую ​​команду, как kill -9 20896. Сигнал по умолчанию — 15, то есть SIGTERM. Имейте в виду, что у многих приложений есть собственный метод остановки. Nginx использует параметр -s для передачи сигнала, такого как «стоп» или «перезагрузка». Как правило, я предпочитаю использовать специальный метод приложения для остановки операции. Тем не менее, я продемонстрирую команду kill, чтобы остановить процесс Nginx 20896, а затем подтвержу, что он остановлен с помощью pgrep. PID 20896 больше не отображается.

УБИЙСТВО

Команда pkill похожа на pgrep тем, что может выполнять поиск по имени. Это означает, что вы должны быть очень осторожны при использовании pkill. В моем примере с Nginx я могу не использовать его, если хочу убить только один экземпляр Nginx. Я могу передать параметр Nginx -s stop конкретному экземпляру, чтобы убить его, или мне нужно использовать grep для фильтрации всего вывода ps.

Если я хочу использовать pkill, я могу включить параметр -f, чтобы заставить pkill фильтровать полный аргумент командной строки. Это, конечно, также относится к pgrep. Итак, сначала я могу проверить с помощью pgrep -a, прежде чем запускать pkill -f.

Я также могу сузить результат с помощью pgrep -f. Тот же аргумент, что и в pkill, останавливает процесс.

Главное, что следует помнить при работе с pgrep (и особенно с pkill), заключается в том, что вы должны всегда быть уверены в том, что результаты поиска точны, чтобы вы непреднамеренно не влияли на неправильные процессы.

Большинство этих команд имеют множество параметров командной строки, поэтому я всегда рекомендую читать справочные страницы по каждой из них. Хотя большинство из них существуют на таких платформах, как Linux, Solaris и BSD, есть несколько отличий. Всегда тестируйте и будьте готовы исправить при необходимости при работе в командной строке или при написании скриптов.

Вы хотите запустить исполняемый файл из вашей программы? Или выполнить команду оболочки программно? Или, может быть, просто распараллелить свой код? Вы прочитали много информации о семействе функций execve() и fork(), но у вас все еще неразбериха в голове? Тогда эта статья для вас.

В Slack полно оповещений Prometheus? Попробуйте Robusta — платформу с открытым исходным кодом, которая ускоряет устранение неполадок Kubernetes. Robusta выявляет шаблоны предупреждений, обогащает предупреждения контекстными данными и помогает избавиться от ложных срабатываний. Проверьте это!

Как запустить процесс Linux

Системные вызовы

Давайте не будем усложнять и начнем с самого начала. Мы разрабатываем программу для Linux. Давайте посмотрим на так называемые системные вызовы — интерфейс, который Linux предоставляет нам для запроса функций ядра.

В Linux есть следующие системные вызовы для работы с процессами:

  • fork(void) ( man 2 fork ) — создает полную копию вызывающего процесса. Звучит неэффективно из-за необходимости копирования адресного пространства процесса ввода, но использует оптимизацию копирования при записи. Это единственный (идеологический) способ создать процесс в Linux. Однако в свежих версиях ядра функция fork() реализована поверх сложного системного вызова clone(), и теперь можно использовать clone() напрямую для создания процессов, но для простоты мы опустим эти детали.
  • execve(path, args, env) (man 2 execve) — преобразует вызывающий процесс в новый процесс, выполняя файл по указанному пути. По сути, он заменяет текущий образ процесса новым образом процесса и не создает новых процессов.
  • pipe(fildes[2] __OUT) ( man 2 pipe ) — создает канал, который является примитивом межпроцессного взаимодействия. Обычно каналы представляют собой однонаправленные потоки данных. Первый элемент массива соединяется с концом чтения канала, а второй элемент соединяется с концом записи. Данные, записанные в fildes[1], можно прочитать из fildes[0].

Мы не собираемся рассматривать исходный код вышеупомянутых системных вызовов, потому что он является частью ядра и его трудно понять.

Также важной частью нашего рассмотрения является оболочка Linux — утилита-интерпретатор команд (т.е. обычная программа). Процесс оболочки постоянно читает из стандартного ввода. Пользователь обычно взаимодействует с оболочкой, вводя некоторые команды и нажимая клавишу ввода. Затем процесс оболочки выполняет предоставленные команды. Стандартные выходные данные этих процессов подключаются к стандартному выводу процесса оболочки. Однако процесс оболочки можно запустить как отдельный подпроцесс, а команду для выполнения можно указать с помощью аргумента -c. Например. bash -c "дата" .

Стандартная библиотека C

Конечно, мы разрабатываем нашу программу на C, чтобы она была максимально приближена к примитивам уровня ОС. C имеет так называемую стандартную библиотеку libc — широкий набор функций для упрощения написания программ на этом языке. Также он обеспечивает обтекание системных вызовов.

Стандартная библиотека C имеет следующие функции (в дистрибутивах на базе Debian apt-get download glibc-source ):

  • system(command) ( man 3 system ) — запускает процесс shell для выполнения предоставленной команды. Вызывающий процесс блокируется до завершения выполнения основного процесса shell. system() возвращает код выхода процесса оболочки. Давайте посмотрим на реализацию этой функции в stdlib:

По сути, system() просто использует комбинацию fork() + exec() + waitpid() .

  • popen(command, mode = 'r|w') ( man 3 popen ) — разветвляет и заменяет разветвленный процесс экземпляром оболочки, выполняющим предоставленную команду. Звучит так же, как system() ? Разница заключается в возможности общаться с дочерним процессом через его стандартный ввод или стандартный вывод. Но обычно в одностороннем порядке. Для связи с этим процессом используется канал. Реальные реализации можно найти здесь и здесь, но основная идея заключается в следующем:

Поздравляем!

Примечание 1. Реализация запуска подпроцесса в shell почти такая же. то есть fork() + execve() .

Примечание 2. Стоит отметить, что другие языки программирования обычно реализуют привязки к libc ОС (и для удобства делают некоторые оболочки), чтобы обеспечить функциональность, специфичную для ОС.

Зачем запускать процесс Linux

Распараллелить выполнение

Самый простой. Нам нужен только fork() . Вызов fork() фактически дублирует ваш программный процесс. Но поскольку этот процесс использует для связи с ним совершенно отдельное адресное пространство, нам все равно нужны примитивы межпроцессного взаимодействия. Даже набор инструкций разветвленного процесса такой же, как у родительского, это другой экземпляр программы.

Просто запустите программу из своего кода

Если вам нужно просто запустить программу без связи с ее стандартным вводом/выводом, функция libc system() является самым простым решением. Да, вы также можете fork() вашего процесса, а затем запустить exec() в дочернем процессе, но поскольку это довольно распространенный сценарий, есть функция system().

Запустить процесс и прочитать его стандартный вывод (или записать в его стандартный ввод)

Нам нужна функция popen() libc. Да, вы по-прежнему можете достичь цели, просто комбинируя pipe() + fork() + exec(), как показано выше, но popen() позволяет сократить объем шаблонного кода.

Запуск процесса, запись в его стандартный ввод и чтение из его стандартного вывода

Самый интересный. По некоторым причинам реализация popen() по умолчанию обычно однонаправленная. Но похоже, что мы можем легко придумать двунаправленное решение: нам нужно два канала, первый будет прикреплен к дочернему стандартному вводу, а второй — к дочернему стандартному выходу. Оставшаяся часть — fork() дочернего процесса, подключение каналов через dup2() к дескрипторам ввода-вывода и выполнение команды execve(). Одну из потенциальных реализаций можно найти в моем проекте GitHub popen2(). Дополнительная вещь, которую вы должны знать при разработке такой функции, это утечка дескрипторов открытых файлов каналов из ранее открытых процессов popen(). Если мы забудем явно закрыть дескрипторы сторонних файлов в каждой дочерней вилке, появится возможность выполнять операции ввода-вывода с одноуровневыми stdin и stdout s. Звучит как уязвимость. Чтобы иметь возможность закрыть все эти файловые дескрипторы, мы должны их отслеживать. Я использовал статическую переменную со связанным списком таких дескрипторов:

Несколько слов о Windows

В семействе ОС Windows используется несколько иная парадигма работы с процессами. Если мы пропустим неотерический уровень совместимости Unix, представленный в Windows 10, и попытаемся портировать поддержку POSIX API для Windows, у нас останется только две функции из старого школьного WinAPI:

    - запускает новый процесс для данного исполняемого файла. - запускает процесс оболочки (да, в Windows тоже есть концепция оболочки) для выполнения предоставленной команды.

Итак, никаких fork и execve. Однако для связи с запущенными процессами также можно использовать каналы.

Вместо выводов

Сделайте код, а не войну!

Автор: Иван Величко

Подпишитесь на меня в Twitter @iximiuz

Присоединяйтесь к более чем тысяче счастливых подписчиков, получающих мой обзор Cloud Native, и получайте подробные технические статьи из этого блога прямо на свой почтовый ящик.

Читайте также: