Запустіть фоновий процес із сценарію та керуйте ним, коли сценарій закінчується


15

Я хотів би запустити і налаштувати процес аналогічно демону зі сценарію.
Моя оболонка емуляція zsh під Cygwin, а демон - SFK , базовий FTP-сервер.

Що тут важливо, сценарій startserv.shможна скласти так:

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
$cmd &

Після запуску сценарію startserv.shвін зупиняється (закінчується?), Не показуючи підказки, тоді:

  • CTRL+ Cзакінчується як сценарієм, так і фоновим завданням;

  • Натискання Enterсценарію закінчується, процес залишається у фоновому режимі.

У будь-якому випадку я бачу це лише через, psа не jobs, тому, коли я хочу закрити процес, мені потрібно надіслати жорстокий kill -9сигнал, чого я хотів би уникати на користь CTRL+ C.

Альтернативою було б запускати весь сценарій у фоновому режимі. 'Було б', але readкоманда не може отримати введення користувача, якщо сценарій запускається як startserv.sh &.

Зауважте, що мені потрібен ефемерний сервер, а не справжній демон : тобто я хочу, щоб серверний процес запускався у фоновому режимі, після закінчення сценарію, для виконання простих інтерактивних завдань оболонки (з гостем віртуальної машини), але я цього не роблю ' t потрібен процес, щоб пережити оболонку; тому nohupздається не підходящим.


отримати ідентифікатор процесу, який працює у фоновому режимі, використовуючи, bgproc="$!"а потім command "$bgproc" вжити відповідних дій. Дивіться також stackoverflow.com/questions/1908610/…
Валентин Байрамі

ви також можете створити PID-файл. Потім прочитайте цей файл, щоб побачити, який це номер процесу, і перейдіть звідти.
jgr208

Відповіді:


18

Натискання Enterсценарію закінчується, процес залишається у фоновому режимі.

Майже! Насправді сценарій вже вийшов з моменту натискання Enter. Однак саме так ви зможете повернути своє запит назад (оскільки оболонка друкує його $PS1знову і знову).

Причина удару Ctrl+ Cприпиняє їх обидва, тому що вони поєднуються. Коли ви виконуєте свій скрипт, оболонка ініціює підшалу, в якій запускати його. Коли ви закінчите цю підзагороду, ваш фоновий процес відмирає, ймовірно, від SIGHUPсигналу.

Відокремте скрипт, фоновий процес і нижню частину

Використовуючи nohup, ви зможете позбутися цієї невеликої незручності.

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
nohup $cmd &

disownальтернатива

Якщо ви можете перейти з /bin/shдо /bin/bash, ви також можете спробувати disown. Щоб дізнатися більше, просто наберіть help disownв bashекземплярі.

disown -h $cmd &

"Приємно" вбити фоновий процес

Тепер, коли мова йде про вбивство вашого процесу, ви можете ідеально робити " Ctrl+ C", використовуючи kill. Тільки не надсилайте жорстоку SIGKILL. Натомість ви можете використовувати:

$ kill -2 [PID]
$ kill -15 [PID]

Що надішле приємне SIGINT(2) або SIGTERM(15) до вашого процесу. Ви також можете роздрукувати значення PID після запуску процесу:

...
nohup $cmd &
echo $!

... а ще краще, змусьте скрипт чекати SIGINT, і відправити його назад у фоновий процес (це дозволить зберегти ваш сценарій на передньому плані) :

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
nohup $cmd &

# Storing the background process' PID.
bg_pid=$!

# Trapping SIGINTs so we can send them back to $bg_pid.
trap "kill -2 $bg_pid" 2

# In the meantime, wait for $bg_pid to end.
wait $bg_pid

Якщо SIGINTнедостатньо, просто використовуйте SIGTERMнатомість (15):

trap "kill -15 $bg_pid" 2 15

Таким чином, коли ваш сценарій отримує SIGINT( Ctrl+ C, kill -2) або деякий SIGTERMчас waitдля фонового процесу, він просто передасть сигнали на нього. Якщо ці сигнали вбивають sfkекземпляр, то waitвиклик повернеться, отже, припиняючи ваш сценарій :)


1
+1 Дуже інформативно. Оскільки скрипт працює в допоміжній оболонці, чи існує можливість доступу з скрипту до таблиці завдань батьківської оболонки сценарію? Це список завдань, що видаються jobsв терміналі після закінчення сценарію (замість ps).
антоніо

1
Завдання пов'язані з вашою поточною оболонкою, вони не передаються від однієї оболонки до іншої. Коли ваша передплата вмирає, її завдання не відновлюються. Друкуючи PID фонового процесу, ви переконайтеся, що зможете легко отримати інформацію про нього навіть після того, як підзарядка закінчиться ( pid -p).
Джон У. Сміт

приємне пояснення, проте якщо ваш сценарій містить більше команд, вони ніколи не виконуються (через wait). Якщо зняти очікування, то обробка сигналу порушена: /
chefarov
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.