Натисніть будь-яку клавішу, щоб призупинити скрипт оболонки, знову натисніть, щоб відновити


11

Я написав скрипт оболонки для тестування API, який копіює файли та повторює його хід після кожного.

Між кожною копією є дві секунди сну, тому я хотів би додати можливість натиснути будь-яку клавішу, щоб призупинити сценарій, щоб дозволити більш глибоке тестування. Потім натисніть будь-яку клавішу для відновлення.

Як я можу додати це якомога менше рядків?

Відповіді:


12

Вам не потрібно щось додавати до свого сценарію. Оболонка дозволяє таку функціональність.

  • Почніть свій скрипт у терміналі.
  • Поки працює і блокує використання терміналу ctrl- z. Термінал знову відпускається, і ви бачите повідомлення про те, що процес зупинений. (Зараз він перебуває у повсякденному стані T, зупинився)
  • Тепер робіть все, що завгодно. Ви також можете запустити інші процеси / скрипти і зупинити їх з ctrl- z.
  • Введіть jobsтермінал або перерахуйте всі зупинені завдання.
  • Щоб продовжувати роботу сценарію, введіть fg(передній план). Він поновлює роботу назад у групі переднього плану, і завдання продовжують виконуватись.

Дивіться приклад:

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

як ви сказали, якщо я запускаю sleep 10; notify-send helloі натискаю CTRL + Z, щоб зупинитись, виконайте notify-send helloвиконання. якщо друга команда виконується, як зупиняється перший процес? після цього, якщо введіть, fgя не бачу нічого, що відбувається, що очевидно, оскільки друга команда вже виконується
Едвард Торвальдс

@edwardtorvalds, оскільки дві команди є окремими. У сценарії вони могли б бути в передній частині. Запишіть їх простим сценарієм та виконайте сценарій. Потім ctrl-z зупиниться, і ви побачите, що друга команда не виконується, поки перша не закінчиться. Писати cmd; cmd; cmd;- це як писати cmd <newline> cmd <newline> .... В якості альтернативи сценарію, який ви можете написати ( cmd; cmd; cmd; ), він поводитиметься як сценарій, окрім нижньої частини, створеної(
хаос

Я також спробував sleep 10. коли я натискаю CTRL + Z через 3 секунди і поновлюється через кілька секунд, і помічає, що команда сну загинула менш ніж за 7 секунд. що протилежне тому, що ви сказали, оскільки команда nevers припиняється, вона просто працює у фоновому режимі.
Едвард Торвальдс

@edwardtorvalds Я також це помітив ... Не має сенсу. Я straced в sleepкоманду і дізнався, що системний виклик використовується nanosleep(). Здається, це визначена поведінка системного nanosleepвиклику. restart_syscall()перезапускає перерваний системний виклик з аргументом часу, відповідним чином налаштованим для врахування часу, який вже минув (включаючи час, коли процес був зупинений сигналом). Прочитайте цю сторінку: man7.org/linux/man-pages/man2/restart_syscall.2.html
хаос

Кілька зауважень для завершення @chaos відповіді (сміливо включайте їх у): коли один ctrl-Z, робота призупиняється ("зупиняється"), тому вона наразі не працює, чекаючи, коли ви вирішите продовжити її на передньому плані (наприклад:) fg %1або на тлі (наприклад:) bg %1. (якщо завдання видає лише 1 число, тобто лише 1 призупинений процес, як показано в прикладі хаосу: тільки [1]+ stopped sleep 10ви можете опустити %nчастину. Якщо є кілька фонових процесів (запущених або зупинених), вам потрібно позначити потрібний з: %n(напр .: fg %2 мати% 2 резюме на передньому плані))
Олів'є Дулак

6

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

Можна використовувати

read -tвстановити час очікування для
read -nчитання одного символу (ефективно просто натисніть будь-яку клавішу) для продовження сценарію

Оскільки ви не надали жодного коду, нижче наводиться приклад того, як його можна було використовувати.
Якщо натиснути q, то read -n1запобігає продовження сценарію, поки не буде натиснута клавіша.
Після натискання клавіші перевірка скидається, і сценарій продовжується в циклі, як звичайно.

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

Ви також можете додати stty -echoдо початку розділу та stty echoдо кінця, щоб запобігти набору тексту не зіпсувати вихідний екран


@mikeserv Я не думаю, що оп не хвилює те, що читається, вони просто хочуть призупинити і відновити сценарій, що ви маєте на увазі, зберігаючи також налаштування терміналу, я змінюю лише один, так що, здається, трохи зайвого.

1
@mikeserv Ага, я просто припускав, що всі stdin будуть надходити від користувача.

1

За допомогою ddвас можна надійно прочитати один байт з файлу. За допомогою нього sttyможна встановити minкількість байтів, щоб визначити термінальне зчитування та timeвихід у десятих частинах секунди. Поєднайте ці два, і ви можете обійтися без sleepповністю, я думаю, і просто дозвольте тайм-ауту зчитування терміналу виконати роботу за вас:

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

Це невеликий приклад whileциклу, який я знущався над вами, щоб спробувати. Кожні дві секунди ddвиводиться на спробу читання stdin- перенаправлення з /dev/tty- і whileциклу циклу. Це або dd НЕ тайм-аут , тому що ви натискаєте кнопку - і в цьому випадку інтерактивна оболонка викликається.

Ось пробний запуск - цифри, надруковані на чолі кожного рядка, є значенням змінної оболонки $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

Якщо ви не користуєтесь stty saneпісля зміни налаштувань stty, я можу помилитися, але це не схоже на те, що ви їх скидаєте десь?

@Jidder - ні, я зберігаю стан терміналу у верхній частині сценарію s=$(stty -g </dev/tty). Одразу після дзвінка ddя потім відновлюю його stty "$s". Стан терміналу не переймається подзаголовками, тому ці настройки залишаються незалежно від батьківської оболонки. stty saneце не обов'язково те, що ви хочете зробити - краще відновити стан так, як ви його знайшли, ніж припускати, що стан був saneу той момент. Якби я не відновлював це, вони echoбули б усюди. Зрозумівши, що це частково, чому я прийшов так пізно - ваша відповідь не була тут, коли я почав тестувати.
mikeserv
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.