Làm thế nào để dừng tập lệnh bash loop trong terminal?


54

Ví dụ,

#!/bin/bash
while :
do
    sl
done

Làm thế nào để chấm dứt tập lệnh bash này?


1
Cho biết thêm chi tiết. Bạn có muốn dừng nó tương tác hoặc lập trình?
manatwork

1
bạn có thể nhấn ctrl-cđể gửi SIGINTtín hiệu (trong hầu hết các shell) hoặc bạn có thể nhấn ctrl-zđể gửi SIGTSTPtín hiệu (trong hầu hết các shell). Trong trường hợp bạn nhấn ctrl-z, quá trình liên quan không bị giết mà bị tạm dừng. Bạn có thể tiếp tục với fg(ít nhất là trong bash)
user1146332

Không, nó không hoạt động!
Yinyanghu

4
Vấn đề không phải là kịch bản, mà là sllệnh mà tôi tin là một lệnh liên tục cho những người viết sai chính tả ls, cho thấy một chuyến tàu đi chậm. Theo như tôi biết thì nó bẫy SIGINTtín hiệu và phải bị giết SIGKILL.

1
Cảm ơn. Không được đóng gói cho bản phân phối của tôi, đó là lý do tại sao tôi không biết / tìm thấy nó. (Tôi nghĩ rằng tôi sẽ không gửi yêu cầu cho nó.)
manatwork

Câu trả lời:


64

Chương trình slcố tình bỏ qua SIGINT, đó là những gì được gửi khi bạn nhấn Ctrl+C. Vì vậy, trước tiên, bạn sẽ cần nói slkhông bỏ qua SIGINTbằng cách thêm -eđối số.

Nếu bạn thử điều này, bạn sẽ nhận thấy rằng bạn có thể dừng từng cá nhân sl, nhưng họ vẫn lặp lại. Bạn cần phải nói bashđể thoát sau SIGINTlà tốt. Bạn có thể làm điều này bằng cách đặt một trap "exit" INTtrước vòng lặp.

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

5
Tôi chưa cài đặt nó để kiểm tra, nhưng bạn cũng có thể giết nó bằng SIGQUIT từ Ctrl- \
derobert

120
  1. nhấn Ctrl-Zđể tạm dừng kịch bản
  2. kill %%

Thông báo %%cho bash tích hợp sẵn killmà bạn muốn gửi tín hiệu (SIGTERM theo mặc định) đến công việc nền bị treo gần đây nhất trong trình bao hiện tại, chứ không phải cho id quy trình.

Bạn cũng có thể chỉ định công việc theo số hoặc theo tên. ví dụ: khi bạn tạm ngưng một công việc với ^ Z, bash sẽ cho bạn biết số công việc của nó với một cái gì đó như thế nào [n]+ Stopped, trong đó ndấu ngoặc vuông là số công việc.

Để biết thêm về điều khiển công việc và trên giết chết công việc, chạy help jobs, help fg, help bg, và help killtrong bash, và tìm kiếm JOB CONTROL(tất cả mũ) hoặc jobspectrong trang bash người đàn ông.

ví dụ

$ ./killme.sh 
./killme.sh: dòng 4: sl: lệnh không tìm thấy
./killme.sh: dòng 4: sl: lệnh không tìm thấy
./killme.sh: dòng 4: sl: lệnh không tìm thấy
./killme.sh: dòng 4: sl: lệnh không tìm thấy
./killme.sh: dòng 4: sl: lệnh không tìm thấy
...
...
...
./killme.sh: dòng 4: sl: lệnh không tìm thấy
^ Z
[1] + Đã dừng ./killme.sh
$ giết %%
$ 
[1] + Đã chấm dứt ./killme.sh

Trong ví dụ này, số của công việc là 1, vì vậy kill %1sẽ hoạt động giống nhưkill %%

(LƯU Ý: Tôi chưa slcài đặt nên đầu ra chỉ là "lệnh không tìm thấy". Trong trường hợp của bạn, bạn sẽ nhận được bất cứ thứ gì sl sản xuất. Nó không quan trọng - ^Ztạm ngưng và kill %%sẽ hoạt động như nhau)


3
Một câu trả lời tốt!
Yinyanghu

2
BTW, để thực hiện nhanh chóng các vòng lặp như thế này, ^ Z có thể là một cách đáng tin cậy hơn để giết quá trình hơn ^ C. ^ C sẽ được gửi đến chương trình ( sl) đang chạy trong vòng lặp, nhưng tập lệnh sẽ tiếp tục chạy ... và bắt đầu một chương trình khác sl. Nếu bạn nhấn ^ C một vài lần thực sự nhanh, bạn có thể giết cả sltập lệnh và tập lệnh (nếu cả hai không bẫy SIGINT). ^ Z sẽ tạm dừng tập lệnh gần như ngay lập tức (ngay lập tức nếu bạn không tính đầu ra được đệm vẫn đang được in tới thiết bị đầu cuối của bạn), vì vậy bạn có thể giết tập lệnh đó bằngkill %%
cas

Chính xác! Tôi phải nói " sllà một chương trình thú vị". Lần này, nó lại vui vẻ với tôi! @ _ @
Yinyanghu

Chỉ trả lời có vẻ cũng hoạt động khi vòng lặp không được gọi từ tập lệnh mà từ trực tiếp dòng lệnh.
Skippy le Grand Gourou

1
@DrewChapin Tôi không thể nhớ khi nào / nơi tôi phát hiện ra về nó - chỉ là thứ tôi đã biết "từ mãi mãi". Trang bash man (tìm kiếm jobspec ) cho biết: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

Nếu bạn muốn ctrl + c dừng vòng lặp, nhưng không chấm dứt tập lệnh, bạn có thể đặt || breaksau bất kỳ lệnh nào bạn đang chạy. Miễn là chương trình bạn đang chạy kết thúc trên ctrl + c, điều này hoạt động rất tốt.

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

Nếu bạn đang ở trong vòng lặp lồng nhau, bạn có thể sử dụng "break 2" để thoát khỏi hai cấp độ, v.v.


cộng 1 cho nghỉ 2
Flyingfinger

3

Bạn có thể chấm dứt tập lệnh đó bằng cách nhấn Ctrl + C từ thiết bị đầu cuối nơi bạn bắt đầu tập lệnh này. Tất nhiên tập lệnh này phải chạy ở nền trước để bạn có thể dừng nó bằng Ctrl + C.

Hoặc bạn có thể tìm thấy PID (ID tiến trình) của tập lệnh đó trong thiết bị đầu cuối đã mở khác bằng cách:

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

Cả hai cách nên làm thủ thuật bạn đang yêu cầu.


1
Nó không thể bị chấm dứt bởi Ctrl + C từ thiết bị đầu cuối. Vì vậy, tôi phải giết nó bằng ps hoặc hàng đầu. Tôi chỉ muốn biết làm thế nào để giết nó trực tiếp!
Yinyanghu

3

Cách dễ nhất là phát QUITtín hiệu, thường được gắn vào Control-Backslash.

Khi bạn nhìn thấy tàu, nhấn Control- \


1

Bạn có thể killpidvỏ (bash).
Tôi chỉ cần thử và nó hoạt động.
Bởi vì tôi không thể thấy quá trình từ ps -ef(công việc mà chúng tôi chạy trong tập lệnh lặp).


0

Một cách khác để chấm dứt toàn bộ tập lệnh sẽ là làm nền cho sllệnh và sau đó bẫy tín hiệu INTđể tiêu diệt toàn bộ nhóm quy trình của tập lệnh bằng tín hiệu HUP.

#!/bin/bash

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

while :
do
   sl & wait
done

-1

sử dụng set -eđể thoát khỏi thất bại.

#!/bin/bash
set -e
while :
do
    sl
done

Điều đó sẽ không làm việc. slkhông chết với ctrl + c.
Duncan X Simpson

-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

Điều này sẽ giúp.


2
Tại sao bạn nghĩ rằng PID của lệnh nền cuối cùng sẽ là 0?
manatwork

-1

Điều giết chóc là khủng khiếp, bởi vì bạn không bao giờ bây giờ, nếu kịch bản phải chạy hai lần. VÀ mã thoát của bạn là sai.

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

Không làm việc. Giải pháp = sử dụng perl. trong khi mở bash riêng

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.