Мне сложно точно сформулировать вопрос, но я сделаю все возможное. Я использую в dwm
качестве моего оконного менеджера по умолчанию иdmenu
как мой запуск приложения. Я почти не использую приложения с графическим интерфейсом, кроме своего браузера. Большая часть моей работы выполняется непосредственно из командной строки. Кроме того, я большой поклонник минимализма в отношении операционных систем, приложений и т. Д. Одним из инструментов, от которого я никогда не избавлялся, была программа запуска приложений. Главным образом потому, что мне не хватает четкого понимания того, как работают программы запуска приложений / что они делают. Даже обширный поиск в Интернете показывает только смутное объяснение. То, что я хочу сделать, - это избавиться даже от моего средства запуска приложений, потому что кроме фактического запуска приложения, я его абсолютно не использую. Для этого мне бы очень хотелось узнать, как «правильно» запускать приложения из оболочки. При этом значение «правильно» может быть аппроксимировано «как бы запускала приложение».
Я знаю о следующих способах порождения процессов из оболочки:
exec /path/to/Program
заменить оболочку указанной командой без создания нового процессаsh -c /path/to/Program
запустить процесс, зависящий от оболочки/path/to/Program
запустить процесс, зависящий от оболочки/path/to/Program 2>&1 &
запустить оболочку независимый процессnohup /path/to/Program &
запустить процесс, независимый от оболочки, и перенаправить вывод вnohup.out
Обновление 1: я могу проиллюстрировать, что, например dmenu
, восстанавливает его из повторных вызовов в ps -efl
различных условиях. Он порождает новую оболочку /bin/bash
и, как потомок этой оболочки, приложение /path/to/Program
. Пока ребенок вокруг, пока вокруг будет раковина. (Как это управляет, я не знаю ...) В отличие от этого, если вы nohup /path/to/Program &
выполняете /bin/bash
команду из оболочки, тогда программа станет дочерней для этой оболочки, НО, если вы выйдете из этой оболочки, родительский процесс программы будет самым верхним процессом. Таким образом, если первый процесс был, например, /sbin/init verbose
и имеет, PPID 1
то он будет родителем программы. Вот что я пытался объяснить с помощью графика: chromium
был запущен с помощью dmenu
, firefox
был запущен с помощью exec firefox & exit
:
systemd-+-acpid
|-bash---chromium-+-chrome-sandbox---chromium-+-chrome-sandbox---nacl_helper
| | `-chromium---5*[chromium-+-{Chrome_ChildIOT}]
| | |-{Compositor}]
| | |-{HTMLParserThrea}]
| | |-{OptimizingCompi}]
| | `-3*[{v8:SweeperThrea}]]
| |-chromium
| |-chromium-+-chromium
| | |-{Chrome_ChildIOT}
| | `-{Watchdog}
| |-{AudioThread}
| |-3*[{BrowserBlocking}]
| |-{BrowserWatchdog}
| |-5*[{CachePoolWorker}]
| |-{Chrome_CacheThr}
| |-{Chrome_DBThread}
| |-{Chrome_FileThre}
| |-{Chrome_FileUser}
| |-{Chrome_HistoryT}
| |-{Chrome_IOThread}
| |-{Chrome_ProcessL}
| |-{Chrome_SafeBrow}
| |-{CrShutdownDetec}
| |-{IndexedDB}
| |-{LevelDBEnv}
| |-{NSS SSL ThreadW}
| |-{NetworkChangeNo}
| |-2*[{Proxy resolver}]
| |-{WorkerPool/1201}
| |-{WorkerPool/2059}
| |-{WorkerPool/2579}
| |-{WorkerPool/2590}
| |-{WorkerPool/2592}
| |-{WorkerPool/2608}
| |-{WorkerPool/2973}
| |-{WorkerPool/2974}
| |-{chromium}
| |-{extension_crash}
| |-{gpu-process_cra}
| |-{handle-watcher-}
| |-{inotify_reader}
| |-{ppapi_crash_upl}
| `-{renderer_crash_}
|-2*[dbus-daemon]
|-dbus-launch
|-dhcpcd
|-firefox-+-4*[{Analysis Helper}]
| |-{Cache I/O}
| |-{Cache2 I/O}
| |-{Cert Verify}
| |-3*[{DOM Worker}]
| |-{Gecko_IOThread}
| |-{HTML5 Parser}
| |-{Hang Monitor}
| |-{Image Scaler}
| |-{JS GC Helper}
| |-{JS Watchdog}
| |-{Proxy R~olution}
| |-{Socket Thread}
| |-{Timer}
| |-{URL Classifier}
| |-{gmain}
| |-{localStorage DB}
| |-{mozStorage #1}
| |-{mozStorage #2}
| |-{mozStorage #3}
| |-{mozStorage #4}
| `-{mozStorage #5}
|-gpg-agent
|-login---bash---startx---xinit-+-Xorg.bin-+-xf86-video-inte
| | `-{Xorg.bin}
| `-dwm-+-dwmstatus
| `-xterm---bash-+-bash
| `-pstree
|-systemd---(sd-pam)
|-systemd-journal
|-systemd-logind
|-systemd-udevd
|-wpa_actiond
`-wpa_supplicant
Обновление 2: я думаю, что вопрос также можно свести к следующему: что должно быть родителем процесса? Должно ли это быть, например, оболочкой или это init
процесс, то есть процесс с PID 1
?
init
- на что ответ может быть ... может быть? это зависит от того, как / если вы планируете поговорить с ним, чтоinit
вы используете и где находятся каналы передачи данных. В общем, эти вещи, как правило, работают само собой - вот для чегоinit
. В любом случае, обычно, когда вы демонизируете процессinit
. Или, если вы хотите контроль работы, текущая оболочка.dmenu
и посмотрю, как я справляюсь с тем, что узнал. Я нахожуexec /path/to/Program & exit
или/bin/bash -c /path/to/Program & exit
быть вполне пригодным для использования. Но все они делают1
тоinit
родителем изProgram
которых хорошо со мной до тех пор , как это имеет смысл , и не нарушает основные*nix
принципы.exec &
, я думаю. Я обычно просто делаю свои вещи из терминала ... может быть, вы бы получили некоторую пользу от вопроса Бена Кроуэлла здесь . У меня есть ответ, но все они очень хорошие. в любом случае, когда вы создаете фоновый процесс и его родитель умирает, как:sh -c 'cat & kill $$'
вы осиротите его, и в конечном итоге он будет пожинен. это работа инициата - вот почему они все к ней относятся.systemd--bash--chromium
. Все методы, которые я пробую, в конечном итоге приводят к дереву процессов следующей формы,systemd--chromium
когда я запускаю firefox из оболочки. Как оболочка демонизируется здесь? Он не связан ни с одним терминалом.Ответы:
Ну, у тебя, кажется, есть хорошее понимание этого. Чтобы уточнить, что у вас есть,
sh -c /path/to/Program
довольно похож нагде вы запускаете новый процесс оболочки, задаете путь команды приложения к новой оболочке, а затем позволяете новой оболочке завершиться. Я показал новую оболочку, дающую другое приглашение в целях иллюстрации; это, вероятно, не произойдет в реальной жизни. Конструкция в основном используется для выполнения хитрых вещей, как упаковка несколько команд в одной связку, так что они выглядят как единая команда (вроде одноразового безымянного сценария), или здания , сложные команд, возможно , от оболочки переменных. Вы вряд ли когда-либо будете использовать его только для запуска одной программы с простыми аргументами.
sh -c "command"
2>&1
означает перенаправление стандартной ошибки на стандартный вывод. Это на самом деле не имеет ничего общего с&
; скорее, вы используете его, когда команда отправляет сообщения об ошибках на экран, даже если вы говорите и хотите записать сообщения об ошибках в файл.command > file
nohup.out
является тривиальным побочным эффектомnohup
. Основная цель состоит в том, чтобы запускаться асинхронно (обычно известный как «в фоновом режиме» или как «процесс, не зависящий от оболочки», чтобы использовать ваши слова) и настраивать его так, чтобы он имел больше шансов продолжить работу, если вы завершить работу оболочки (например, выйти из системы), пока команда еще выполняется.nohup command &
command
bash(1)
и Справочное руководство Bash являются хорошими источниками информации.источник
Есть несколько способов выполнить программу и отсоединить ее от терминала. Один из них - запустить его в фоновом режиме подоболочки (замените его
firefox
на свою любимую программу):Другой способ отказаться от процесса:
Если вы хотите знать , как приложение пусковые работы,
dmenu
обеспечивает 1 двоичный и 2 сценарии оболочки:dmenu
,dmenu_path
иdmenu_run
, соответственно.dmenu_run
dmenu_path
направляет вывод в dmenu, которое, в свою очередь, направляет в любую вашу$SHELL
переменную. Если он пуст, он будет использовать/bin/sh
.dmenu_path
это немного сложнее, но вкратце он предоставляет список двоичных файлов в вашей$PATH
переменной среды и использует кеш, если это возможно.Нет необходимости запускать программы в оболочках. Другой способ написать
dmenu_run
без использования оболочки:источник
Мне очень нравится ответ G-Man. Но я отвечаю, потому что я думаю, что вы сбиваете с толку проблемы. Как указывает Уэйн, лучший ответ - «все, что дает желаемый результат».
В управлении процессами Unix у каждого процесса есть родитель. Единственным исключением является
init
процесс, который запускается ОС при загрузке. Это нормальное поведение для родительского процесса, чтобы взять все его дочерние процессы с собой, когда он умирает. Это делается путем отправки сигнала SIGHUP всем дочерним процессам; обработка SIGHUP по умолчанию завершает процесс.Порождение пользовательских процессов в оболочке ничем не отличается от того, что вы кодировали вызовы fork (2) / exec (3) на выбранном вами языке. Оболочка является вашим родителем, и если оболочка завершается (например, вы выходите из системы), то дочерний процесс (-ы), который она порождает, идет вместе с ним. Нюансы, которые вы описываете, являются просто способами изменения этого поведения.
exec /path/to/program
это как вызов exec (3) . Да, он заменит вашу оболочкуprogram
, оставив родительский элемент, запустивший оболочку.sh -c /path/to/program
вид бессмысленно создает дочерний процесс оболочки, который будет создавать дочерний процессprogram
. Это полезно только в том случае, если/path/to/program
на самом деле это последовательность инструкций скрипта, а не исполняемый файл. (sh /path/to/script.sh
может использоваться для запуска сценария оболочки, который не имеет разрешений на выполнение в подчиненной оболочке)/path/to/program
создает процесс «переднего плана», означающий, что оболочка ожидает завершения процесса, прежде чем предпринимать какие-либо другие действия. В контексте системного вызова это похоже на fork (2) / exec (3) / waitpid (2) . Обратите внимание, что ребенок наследует stdin / stdout / stderr от родителя./path/to/program &
(игнорируя перенаправление) создает «фоновый процесс». Процесс по-прежнему является дочерним элементом оболочки, но родитель не ожидает его завершения.nohup /path/to/program
вызывает nohup (1) для предотвращения отправки SIGHUP,program
если управляющий терминал закрыт. Находится ли он на переднем плане или на заднем плане - выбор (хотя чаще всего этот процесс основан на заднем плане). Обратите внимание, чтоnohup.out
это только вывод, если вы не перенаправите иначе stdout.Когда вы помещаете процесс в фоновый режим, если родительский процесс умирает, происходит одно из двух. Если родитель является управляющим терминалом , то SIGHUP будет отправлено детям. Если это не так, то процесс может быть «осиротевшим» и наследоваться
init
процессом.Когда вы перенаправляете ввод / вывод / ошибку, вы просто подключаете файловые дескрипторы, которые каждый процесс имеет к файлам, отличным от тех, которые он наследует от своего родителя. Ничто из этого не влияет на владение процессом или глубину дерева (но всегда имеет смысл перенаправить все 3 из терминала для фоновых процессов).
Учитывая все вышесказанное, я не думаю, что вам следует беспокоиться о создании процессов с помощью оболочки, вложенных оболочек или подпроцессов, если только вы не столкнулись с конкретной проблемой, связанной с управлением процессами.
источник
sh -c /path/to/program
не будет запускать программу как скрипт оболочки, если в ней отсутствуют исполняемые биты,sh /path/to/program
будет.sh -c /path/to/program
просто откроет оболочку и запустит/path/to/program
команду в этой оболочке, что приведет к ошибке, если она не исполняется.sh -c /path/to/program
читает команды из/path/to/program
ввода в оболочку. Это не требует, чтобы файл имел разрешение на выполнение, но это должен быть сценарий оболочкиsh /path/to/program
делает это. Просто сам попробовал:,echo echo hello world >abc.sh
потомsh ./abc.sh
печатаетhello world
, покаsh -c ./abc.sh
говоритsh: ./abc.sh: Permission denied
(что то же самое, как если бы вы запускали./abc.sh
в текущей оболочке напрямую.) Я что-то пропустил? (Или, может быть, я не выразил себя хорошо в предыдущем комментарии ...)sh -c _something_
это то же самое, что просто набирать_something_
в командной строке, за исключением порождения нижней оболочки. Таким образом, вы правы, что произойдет сбой, если пропустить бит выполнения (в виде файла). С другой стороны, вы можете предоставить ряд команд оболочки, например,sh -c "echo hello world"
и все будет работать отлично. Поэтому не требуется, чтобы то, что вы вводите, имело бит выполнения (или даже файл), только то, что интерпретатор оболочки может что-то с ним сделать.