LinuxForum.Fans
Тема

Остановка bash-скрипта

Автор: valet 30 сообщений 9782 просмотров
#283387

Есть bash-скрипт script примерно следующего содержания:

text
cat file | xargs -t -P 1 -n1 ./script2

С запуском никаких проблем нет ./script, но вот как его остановить. Ctrl+C не подходит конечно, так как останавливать планирую по cron.
вариации на тему kill -15 script или kill -9 script не работают, так как в даном случае там и cat и xargs да еще и старт другого скрипта, в котором тоже целый набор стандартных команд.
Знаю что можно оформить в виде сервиса, так как это сделано в скриптах /etc/init.d/. Но для меня это слишком сложно, опыта не хватает, чтобы разобрать варианты, которые там есть. Нагугленные варианты на эту тему у меня почему-то не работают.

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

#283395

[console]$ cat script.sh[/console]

text

#!/bin/bash
time cat

[console]$ ./script.sh[/console]
Одновременно в другой консоли
[console]$ ps -A | grep script
19041 pts/6 00:00:00 script.sh
$ sudo killall script.sh
[/console]
Скрипт останавливается. Ч. т. д. ?

#283396

Хотя не, cat продолжает висеть в процессах....

#283408

"-=Serj=-" написал:
Хотя не, cat продолжает висеть в процессах....
да, в этом то и проблема.
#283446

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

#283453

На коленке можно сделать такой вариант:
Скрипт периодически проверяет наличие контрольного файла в /tmp. Если файла нет, то скрипт работает, если файл есть, то скрипт завершает работу.
Соответственно для остановки скрипта достаточно выполнить touch /tmp/control_file.

Я не утверждаю, что это оптимально, или правильно, но это должно сработать. А потом уже можно читать документацию и думать как это реализовать более изящно.

#283456

"pitdron" написал:
Так вы попробуйте завершать cat, т.к. он является родительским процессом для других.
Так подход неправильный - другие скрипты могут тоже использовать cat и их нельзя обрывать.
#283457
Vascom написал:
На коленке можно сделать такой вариант:
Скрипт периодически проверяет наличие контрольного файла в /tmp. Если файла нет, то скрипт работает, если файл есть, то скрипт завершает работу.
Соответственно для остановки скрипта достаточно выполнить touch /tmp/control_file.

Я не утверждаю, что это оптимально, или правильно, но это должно сработать. А потом уже можно читать документацию и думать как это реализовать более изящно.

Идея интересная, но сомнительно это все. Ну вот куда в моем примере всунуть проверку на существования тем-файла? Надо еще учитывать что тот же xargs может работать многопоточно - соответственно тем более непонятно куда проверку на существование файла всунуть...
Ну и да - неуниверсально смотрится.

Неужели нету какго-то элементарного метода убить bash-скрипт. Я думал это я чего-то не знаю, а сейчас начинаю понимать, что не все так просто.

#283458
"valet" написал:
cat file | xargs -t -P 1 -n1 ./script2

Через screen сделай.

#283459

На самом деле всё просто. Только скрипт надо изначально писать правильно. Всякие внешние убивалки - это экстренная ситуация. Завершение скрипта должно быть предусмотрено в нём самом, иначе всегда будет криво и неоднозначно.

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

#283462
"pitdron" написал:
Так вы попробуйте завершать cat, т.к. он является родительским процессом для других.

не верно, cat ни чьим родителем не является. и не сработает, если xargs длительный...

"Vascom" написал:
На коленке можно сделать такой вариант:Скрипт периодически проверяет наличие контрольного файла в /tmp. Если файла нет, то скрипт работает, если файл есть, то скрипт завершает работу.Соответственно для остановки скрипта достаточно выполнить touch /tmp/control_file.Я не утверждаю, что это оптимально, или правильно, но это должно сработать. А потом уже можно читать документацию и думать как это реализовать более изящно.

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

#283467

"Fat-Zer" написал:
xargs длительный...
он очень длительный, практически бесконечный и выполняет однотипные операции. Поэтому появилась идея запускать и останавливать периодически по крону.

"Fat-Zer" написал:
что в script2 есть услышать было бы хорошо...
ну я так примеру дал, не важно что там, вариантов много и они у меня используются, ну к примеру:
script2 такой:
text
#!/bin/bash

site=$1

sort -R index -o index cat index|awk '{print rand()"\t"$0}'|sort|awk -F'\t' '{print $2}' > 1_"$site"

"Fat-Zer" написал:
если script2 какую-то длительную операцию запускает...
опять таки по разному есть, например в этом варианте - да - операция длительная.
#283468

"Vascom" написал:
На самом деле всё просто. Только скрипт надо изначально писать правильно. Всякие внешние убивалки - это экстренная ситуация. Завершение скрипта должно быть предусмотрено в нём самом, иначе всегда будет криво и неоднозначно.
А если он бесконечный или практически бесконечный, так как обрабатывается множество однотипных данных.
#283469

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

#283471
valet написал:
Vascom, дайте пожалуйста конкретный пример как вы остановите скрипт при проверки наличия файла. Я честно говоря вообще не знаю как можно выходить из скрипта пока он еще не завершился.

я так понял это имелось в виду:

text

for ((i=0; i<100500; i++)); do
  sleep 1
  [ -f /path/to/stop/file ] && break
done

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

"valet" написал:
sort -R index -o index
cat index|awk '{print rand()"\t"$0}'|sort|awk -F'\t' '{print $2}' > 1_"$site"

а то, в каком порядке sort отсортировал вам не понравилось О_о ?

#283473
valet написал:
Vascom, дайте пожалуйста конкретный пример как вы остановите скрипт при проверки наличия файла. Я честно говоря вообще не знаю как можно выходить из скрипта пока он еще не завершился.

Примерно так

text
#!/bin/bash

function very_long_process() { sleep 30 echo AA touch /tmp/control }

# Start long process in background very_long_process &

#Check control file while [ ! -e "/tmp/control" ] do sleep 5 done kill -9 "$!"

Роль длинного процесса выполняет команда sleep 30, то есть он будет идти 30 секунд и в результате выдаст на экран "AA". Запускаем его в бэкграунде, затем каждые 5 секунд проверяем появление контрольного файла. Если файл появился, то прерываем наш длинный процесс. Если же процесс выполнился нормально, то контрольный файл появится сам и мы снова выходим из скрипта.

$! - pid последнего процесса в фоновом режиме

#283479
"Vascom" написал:
Роль длинного процесса выполняет команда sleep 30, то есть он будет идти 30 секунд и в результате выдаст на экран "AA". Запускаем его в бэкграунде, затем каждые 5 секунд проверяем появление контрольного файла. Если файл появился, то прерываем наш длинный процесс. Если же процесс выполнился нормально, то контрольный файл появится сам и мы снова выходим из скрипта.$!  -  pid последнего процесса в фоновом режиме

sleep будет работать до победного конца - все 30 секунд...

#283480
Fat-Zer написал:
[quote="Vascom"]Роль длинного процесса выполняет команда sleep 30, то есть он будет идти 30 секунд и в результате выдаст на экран "AA". Запускаем его в бэкграунде, затем каждые 5 секунд проверяем появление контрольного файла. Если файл появился, то прерываем наш длинный процесс. Если же процесс выполнился нормально, то контрольный файл появится сам и мы снова выходим из скрипта.$!  -  pid последнего процесса в фоновом режиме

sleep будет работать до победного конца - все 30 секунд...[/quote]
Не будет. Я проверил работу скрипта. "АА" не выдаётся в консоль.

#283483
"Vascom" написал:
Не будет. Я проверил работу скрипта.
text
alexander@goblin /tmp $ cat ./script3.sh
#!/bin/bash

function very_long_process() { sleep 300 echo AA touch "/tmp/control" }

# Start long process in background very_long_process &

#Check control file while [ ! -e "/tmp/control" ] do sleep 5 done kill "$!" rm "/tmp/control" alexander@goblin /tmp $ ./script3.sh & [1] 15047 alexander@goblin /tmp $ ps aux | grep sleep && touch /tmp/control && ps aux | grep sleep && sleep 5 && ps aux | grep sleep && sleep 5 && ps aux | grep sleep1000 15050 0.0 0.0 7724 624 pts/9 S 12:54 0:00 sleep 300 1000 15055 0.0 0.0 7724 624 pts/9 S 12:55 0:00 sleep 5 1000 15057 0.0 0.0 10300 916 pts/9 S+ 12:55 0:00 grep --colour=auto sleep 1000 15050 0.0 0.0 7724 624 pts/9 S 12:54 0:00 sleep 300 1000 15055 0.0 0.0 7724 624 pts/9 S 12:55 0:00 sleep 5 1000 15060 0.0 0.0 10300 916 pts/9 S+ 12:55 0:00 grep --colour=auto sleep ./script3.sh: line 19: 15048 Завершено very_long_process [1]+ Done ./script3.sh 1000 15050 0.0 0.0 7724 624 pts/9 S 12:54 0:00 sleep 300 1000 15064 0.0 0.0 10300 916 pts/9 S+ 12:55 0:00 grep --colour=auto sleep 1000 15050 0.0 0.0 7724 624 pts/9 S 12:54 0:00 sleep 300 1000 15067 0.0 0.0 10300 916 pts/9 S+ 12:55 0:00 grep --colour=auto sleep

"Vascom" написал:
"АА" не выдаётся в консоль.

не выдаётся, но sleep работает

ЗЫ: можно ещё нашаманить что-нить с перехватом сигналов...

#283489

Нда, может я и не прав. Но общий принцип понятен.
Может не надо в функцию это оформлять, а саму команду в бэкграунд пустить и её pid запомнить в переменную.

Войдите или зарегистрируйтесь, чтобы ответить.