Як зупинити скрипт bash bash в терміналі?


54

Наприклад,

#!/bin/bash
while :
do
    sl
done

Як припинити цей сценарій bash?


1
Дайте більше деталей. Ви хочете зупинити це в інтерактивному чи програмному плані?
манатура

1
Ви можете натиснути, ctrl-cщоб надіслати SIGINTсигнал (у більшості оболонок) або натиснути, ctrl-zщо передає SIGTSTPсигнал (у більшості оболонок). У випадку, якщо ви натиснули ctrl-zвідповідний процес, не вбиваєтесь, а призупиняєте. Ви можете відновити його fg(принаймні в bash)
user1146332

Ні, це не працює!
Yinyanghu

4
Проблема не в сценарії, а в slкоманді, на яку я вважаю, це набридлива команда для тих, хто неправильно написав ls, показуючи поїзд, що проїжджає повільно. Наскільки я знаю, він затримує SIGINTсигнал і його потрібно вбити SIGKILL.

1
Дякую. Не упакований для мого дистрибутива, тому я цього не знав / знайшов. (Думаю, я не буду подавати заявку на це.)
манатура

Відповіді:


64

Програма slнавмисно ігнорує SIGINT, що надсилається при натисканні Ctrl+C. Отже, по-перше, вам потрібно буде сказати slне ігнорувати SIGINT, додавши -eаргумент.

Якщо ви спробуєте це, ви помітите, що можете зупинити кожного окремого sl, але вони все одно повторюються. Вам також потрібно сказати, bashщоб вийти SIGINT. Це можна зробити, поставивши trap "exit" INTперед циклом.

#!/bin/bash
trap "exit" INT
while :
do
    sl -e
done

5
У мене його не встановлено, щоб перевірити, але ви також можете вбити його за допомогою SIGQUIT від Ctrl- \
derobert

120
  1. натисніть, Ctrl-Zщоб призупинити сценарій
  2. kill %%

%%Каже Баш вбудованих в killтому , що ви хочете , щоб послати сигнал (SIGTERM за замовчуванням) останнім часом призупинено фонове завдання в поточному оболонці, а нема на ідентифікатор процесу.

Ви також можете вказати завдання за номером або іменем. наприклад, коли ви призупиняєте роботу з ^ Z, bash скаже вам, що таке номер завдання з чимось на зразок [n]+ Stopped, де nвсередині квадратних дужок є номер завдання.

Для отримання додаткової інформації про контроль роботи і на вбивство робочих місць, біг help jobs, help fg, help bg, і help killв БАШЕЄВ і пошук JOB CONTROL(великі літери) або jobspecна сторінці Баша людини.

напр

$ ./killme.sh 
./killme.sh: рядок 4: sl: команда не знайдена
./killme.sh: рядок 4: sl: команда не знайдена
./killme.sh: рядок 4: sl: команда не знайдена
./killme.sh: рядок 4: sl: команда не знайдена
./killme.sh: рядок 4: sl: команда не знайдена
...
...
...
./killme.sh: рядок 4: sl: команда не знайдена
^ Z
[1] + Зупинено ./killme.sh
$ kill %%
$ 
[1] + Припинено ./killme.sh

У цьому прикладі кількість роботи становила 1, тому kill %1працювала б так само, як іkill %%

(ПРИМІТКА. У мене не slвстановлено, тому вихід - це просто "команда не знайдена". У вашому випадку ви отримаєте все, що видає сл. Вихідне. Це не важливо - ^Zпризупинити і kill %%буде працювати те саме)


3
Ще одна гарна відповідь!
Yinyanghu

2
BTW, для швидкого виконання подібних циклів, ^ Z може бути більш надійним способом вбити процес, ніж ^ C. ^ C буде надіслано програмі ( sl), що запускається в циклі, але сценарій буде продовжувати працювати ... і запустити інший sl. Якщо натиснути ^ C кілька разів по-справжньому швидко, ви можете вбити slі скрипт, і сценарій (якщо жоден з них не потрапить у SIGINT). ^ Z припинить сценарій майже негайно (негайно, якщо ви не рахуєте буферний вихід, який все ще надрукується на ваш термінал), тож ви можете його вбитиkill %%
cas

Саме так! Я мушу сказати " slце весела програма". Цього разу це мене знову розважило! @ _ @
Yinyanghu

Відповідь, яка, здається, працює також і тоді, коли цикл викликається не зі скрипту, а безпосередньо з командного рядка.
Skippy le Grand Gourou

1
@DrewChapin Я не можу згадати, коли / де я дізнався про це - просто щось, що знаю "з віків". Сторінка Баш людина (пошук jobspec ) говорить:The symbols %% and %+ refer to the shell's notion of the current job, which is the last job stopped while it was in the foreground or started in the background. The previous job may be referenced using %-. If there is only a single job, %+ and %- can both be used to refer to that job
Cas

6

Якщо ви хочете, щоб ctrl + c зупинив цикл, але не припиняв сценарій, ви можете розмістити його || breakпісля будь-якої команди, яку ви виконуєте. Поки програма, яку ви запускаєте, закінчується на ctrl + c, це чудово працює.

#!/bin/bash
while :
do
    # ctrl+c terminates sl, but not the shell script
    sl -e || break
done

Якщо ви знаходитесь у вкладеному циклі, ви можете скористатися "break 2", щоб вийти з двох рівнів тощо.


плюс 1 за перерву 2
flyingfinger

3

Ви можете скасувати цей скрипт, натиснувши Ctrl + C з терміналу, де ви запустили цей сценарій. Звичайно, цей сценарій повинен працювати на передньому плані, щоб ви могли зупинити його Ctrl + C.

Або ви можете знайти PID (ідентифікатор процесу) цього сценарію в іншому відкритому терміналі:

ps -ef | grep <name_of_the_script>
kill -9 <pid_of_your_running_script>

Обидва способи повинні зробити трюк, про який ви просите.


1
Він не може бути припинений Ctrl + C з терміналу. Тож я маю його вбити за допомогою ps чи top. Я просто хочу знати, як це вбити безпосередньо!
Yinyanghu

3

Найпростіший спосіб - видавати QUITсигнал, до якого зазвичай приєднується Control-Backslash.

Коли ви побачите поїзд, натисніть кнопку Control- \


1

Ви можете оболонки (Баш). Я просто спробував, і це працює. Тому що я не можу бачити процес (завдання, яке ми виконуємо в циклі).killpid

ps -ef


0

Іншим способом припинити весь скрипт було б подати slкоманду, а потім INTподати сигнал, щоб убити всю групу процесу сценарію сигналом HUP.

#!/bin/bash

trap 'trap - INT; kill -s HUP -- -$$' INT
#trap 'trap - INT; kill -s HUP 0' INT

while :
do
   sl & wait
done


-1
while [ true ] 
do

  #check if script is running
  ps | grep script_name.sh | grep -v grep >/dev/null 2>&1

  if [ "$!" != "0" ] ; then
    break
  else

    kill -9 ` ps -ef | grep script_name.sh | cut -d "a" -f 1` 
    echo "kill -9 `get script PID`"

  fi

done

це має допомогти.


2
Чому ви вважаєте, чому PID останньої фонової команди коли-небудь буде 0?
манатура

-1

Справа вбивства жахлива, тому що ви ніколи зараз, якщо сценарій повинен запускатися двічі. І ваш код виходу неправильний.

while [ something ]; do

 if [ somethingelse ]; then
   echo shut down script with exit code 0
   exit 0
 fi
done

echo something else not happend
exit 2 # Return val important for example for monitoring

Не працює. Рішення = використовувати perl. при цьому відкриває власний баш

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