Nhấn phím bất kỳ để tạm dừng tập lệnh shell, nhấn lần nữa để tiếp tục


10

Tôi đã viết một tập lệnh shell để kiểm tra một API sao chép các tập tin và lặp lại tiến trình của nó sau mỗi tập lệnh.

Có một giấc ngủ hai giây giữa mỗi bản sao, vì vậy tôi muốn thêm khả năng nhấn bất kỳ phím nào để tạm dừng tập lệnh để cho phép thử nghiệm sâu hơn. Sau đó nhấn phím bất kỳ để tiếp tục.

Làm thế nào tôi có thể thêm điều này trong càng ít dòng càng tốt?

Câu trả lời:


12

Bạn không cần phải thêm một cái gì đó vào kịch bản của bạn. Vỏ cho phép một chức năng như vậy.

  • Bắt đầu kịch bản của bạn trong một thiết bị đầu cuối.
  • Trong khi đang chạy và chặn sử dụng thiết bị đầu cuối ctrl- z. Thiết bị đầu cuối được phát hành lại và bạn thấy một thông báo rằng quá trình được dừng lại. (Bây giờ nó đang ở trạng thái porcess T, dừng lại)
  • Bây giờ làm bất cứ điều gì bạn muốn. Bạn cũng có thể bắt đầu các quy trình / tập lệnh khác và dừng chúng bằng ctrl- z.
  • Nhập jobsvào thiết bị đầu cuối hoặc liệt kê tất cả các công việc đã dừng.
  • Để cho tập lệnh của bạn tiếp tục, hãy nhập fg(tiền cảnh). Nó tiếp tục công việc trở lại nhóm quy trình tiền cảnh và các công việc tiếp tục chạy.

Xem một ví dụ:

root@host:~$ sleep 10 # sleep for 10 seconds
^Z
[1]+  Stopped                 sleep 10
root@host:~$ jobs # list all stopped jobs
[1]+  Stopped                 sleep 10
root@host:~$ fg # continue the job
sleep 10
root@host:~$ # job has finished

như bạn đã nói, nếu tôi chạy sleep 10; notify-send hellovà nhấn CTRL + Z để dừng, notify-send hellohãy thực hiện. Nếu lệnh thứ hai được thực thi thì làm sao quá trình đầu tiên bị dừng? sau đó nếu loại fgtôi không thể thấy bất cứ điều gì xảy ra, điều đó là hiển nhiên, vì lệnh thứ hai đã được thực thi
Edward Torvalds

@edwardtorvalds vì hai lệnh riêng biệt. Trong một kịch bản, họ sẽ ở trong một subshell. Viết chúng trong một kịch bản đơn giản và thực hiện kịch bản. Sau đó ctrl-z dừng lại và bạn sẽ thấy lệnh thứ hai không được thực thi cho đến khi lệnh đầu tiên kết thúc. Viết cmd; cmd; cmd;cũng giống như viết cmd <newline> cmd <newline> .... Ngoài ra, đối với một tập lệnh mà bạn có thể viết ( cmd; cmd; cmd; ), nó sẽ hoạt động giống như tập lệnh, phần phụ của phần con được tạo bởi(
hỗn loạn

tôi cũng đã cố gắng sleep 10. khi tôi nhấn CTRL + Z sau 3 giây và tiếp tục lại sau vài giây và nhận thấy lệnh ngủ đã chết trong vòng chưa đầy 7 giây. trái ngược với những gì bạn nói, vì lệnh nevers bị dừng nên nó chỉ chạy trong nền.
Edward Torvalds

@edwardtorvalds Tôi cũng nhận thấy điều đó ... Không có nghĩa gì cả. Tôi straced sleeplệnh và phát hiện ra rằng cuộc gọi hệ thống được sử dụng là nanosleep(). Nó dường như là một hành vi được xác định của nanosleephệ thống. restart_syscall()khởi động lại cuộc gọi hệ thống bị gián đoạn với một đối số thời gian được điều chỉnh phù hợp để tính đến thời gian đã trôi qua (bao gồm cả thời gian mà quá trình bị dừng bởi tín hiệu). Đọc manpage đó: man7.org/linux/man-pages/man2/restart_syscall.2.html
hỗn loạn

Một số lưu ý để hoàn thành câu trả lời @chaos (vui lòng đưa chúng vào): khi một người thực hiện ctrl-Z, công việc bị đình chỉ ("dừng lại"), vì vậy hiện tại nó không chạy, chờ bạn quyết định tiếp tục ở nền trước (ví dụ fg %1:) hoặc nền (ví dụ bg %1:). (nếu các công việc chỉ đưa ra 1 số, tức là chỉ có 1 quy trình bị đình chỉ, như trong sự hỗn loạn mẫu mực cho thấy: chỉ [1]+ stopped sleep 10, bạn có thể bỏ qua %nphần đó. Nếu có một số quy trình nền (đang chạy hoặc dừng), bạn cần chỉ định quy trình bạn muốn với: %n(ví dụ: fg %2 để có% 2 tiếp tục ở phía trước))
Olivier Dulac

6

Nếu bạn muốn tạm dừng tập lệnh trong khi vẫn ở trong tập lệnh thì bạn có thể sử dụng đọc thay vì ngủ.

Bạn có thể dùng

read -tđể đặt thời gian chờ để đọc
read -nđể đọc một ký tự (thực tế chỉ cần nhấn bất kỳ phím nào) để tiếp tục tập lệnh

Như bạn chưa cung cấp bất kỳ mã nào, dưới đây là một ví dụ về cách sử dụng nó.
Nếu q được nhấn thì read -n1ngăn tập lệnh tiếp tục cho đến khi nhấn phím.
Khi nhấn một phím thì kiểm tra được đặt lại và tập lệnh tiếp tục trong vòng lặp như bình thường.

while [[ true ]]; do
    read -t2 -n1 check
    if [[ $check == "q" ]];then
        echo "pressed"
        read -n1
        check=""
    else
        echo "not pressed"
    fi
echo "Doing Something"
done

Bạn cũng có thể thêm stty -echovào đầu phần và stty echocuối để ngăn việc gõ làm rối màn hình đầu ra


@mikeerv Tôi không nghĩ op quan tâm đến những gì đã đọc, họ chỉ muốn tạm dừng và tiếp tục tập lệnh, ý bạn là gì khi lưu cài đặt thiết bị đầu cuối, tôi chỉ thay đổi một cái để có vẻ hơi quá.

1
@mikeerv ahh đúng rồi, tôi chỉ cho rằng tất cả stdin sẽ đến từ người dùng.

1

Với ddbạn có thể đọc một byte đáng tin cậy từ một tệp. Với sttybạn có thể thiết lập một minsố byte để đủ điều kiện đọc thiết bị đầu cuối và timehết trong một phần mười giây. Tôi kết hợp cả hai và bạn có thể làm mà không cần sleephoàn toàn, tôi nghĩ, và chỉ để thời gian chờ đọc của thiết bị đầu cuối thực hiện công việc cho bạn:

s=$(stty -g </dev/tty)
(while stty raw -echo isig time 20 min 0;test -z "$(
dd bs=1 count=1 2>/dev/null; stty "$s")" || (exec sh)
do echo "$SECONDS:" do your stuff here maybe                             
   echo  no sleep necessary, I think                                                          
   [ "$((i+=1))" -gt 10 ] && exit                                                             
done       
) </dev/tty

Đó là một whilevòng lặp ví dụ nhỏ mà tôi đã thử để bạn thử. Cứ sau hai giây ddlại đọc thử stdin- chuyển hướng từ /dev/tty- và các whilevòng lặp. Điều đó hoặc dd không hết thời gian vì bạn nhấn một phím - trong trường hợp đó, một vỏ tương tác được gọi.

Đây là một lần chạy thử - các số được in ở đầu mỗi dòng là giá trị của biến shell $SECONDS:

273315: do your stuff here maybe
no sleep necessary, I think
273317: do your stuff here maybe
no sleep necessary, I think
273319: do your stuff here maybe
no sleep necessary, I think
273321: do your stuff here maybe
no sleep necessary, I think
sh-4.3$ : if you press a key you get an interactive shell
sh-4.3$ : this example loop quits after ten iterations
sh-4.3$ : or if this shell exits with a non-zero exit status
sh-4.3$ : and speaking of which, to do so you just...
sh-4.3$ exit
exit
273385: do your stuff here maybe
no sleep necessary, I think
273387: do your stuff here maybe
no sleep necessary, I think
273389: do your stuff here maybe
no sleep necessary, I think
273391: do your stuff here maybe
no sleep necessary, I think
273393: do your stuff here maybe
no sleep necessary, I think
273395: do your stuff here maybe
no sleep necessary, I think
273397: do your stuff here maybe
no sleep necessary, I think

Bạn không nên sử dụng stty sanesau khi thay đổi cài đặt stty, tôi có thể sai nhưng có vẻ như bạn không đặt lại chúng ở bất cứ đâu?

@Jidder - không tôi lưu trạng thái của thiết bị đầu cuối ở đầu tập lệnh với s=$(stty -g </dev/tty). Ngay sau khi gọi ddtôi thì khôi phục lại stty "$s". Trạng thái thiết bị đầu cuối không quan tâm đến các lớp con và vì vậy các cài đặt đó dính bất kể vỏ cha. stty sanekhông nhất thiết là những gì bạn muốn làm - tốt hơn là khôi phục trạng thái theo cách bạn đã tìm thấy hơn là giả định trạng thái saneở thời điểm đó. Nếu tôi không khôi phục nó thì những thứ đó echosẽ ở khắp mọi nơi. Chỉ ra rằng đó là một phần lý do tại sao tôi đến muộn - câu trả lời của bạn không ở đây khi tôi bắt đầu thử nghiệm.
mikeerv
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.