Как я корректно приостанавливаю и возобновляю цепочку 'cmd1 && cmd2 && cmd3'?

Вы звоните main функция без аргумента. Так $# в основной функции всегда 0.

Каждый функциональный экземпляр имеет свои собственные аргументы. (“Экземпляр” означает, что, если функция запускается многократно (через рекурсивные вызовы), каждый вызов имеет свои собственные аргументы.) Позиционные параметры $1, $2, и т.д., а также связанные параметры $#, $* и $@ обратитесь к аргументам, переданным в вызове функции. Например, если Вы звоните main foo bar затем в main функционируйте значение $1 будет foo, значение $# будет 2 и так далее.

Если Вы хотите передать аргументы сценария к функции, использовать "$@". Эта конструкция расширяется до списка аргументов, переданных сценарию (или функции, если названо в функции). Обратите внимание, что в отличие от того, что обычно происходит с двойными кавычками, параметры передаются отдельно, "$@" список строк и ни одной строки. Двойные кавычки необходимы, иначе параметры не передаются, как всего лишь рассматривается как разделенный от пробела список шаблонов имени файла.

function main {
  if (( $# < 1 )); then
    usage
  fi
  echo "good"
}
main "$@"
5
13.04.2017, 15:36
3 ответа

Я думаю, что вы неправильно интерпретируете происходящее. Когда вы это делаете:

cmd1 && cmd2

оболочка запускает cmd1 в дочернем процессе, ждет этого процесса, а затем запускает cmd2, если cmd1 выходит со статусом нулевого выхода.

Если нажать Ctrl+Z, ожидание вернется, оболочка установит $? на 148, например (128 + SIGTSTP), а оценка остального произойдет в этот момент , поэтому cmd2 будет не выполнена. И cmd1 становится фоновым заданием.

Если бы вы набрали:

cmd1 || cmd2

или:

cmd1; cmd2

cmd2 была бы выполнена на Ctrl-Z и вам пришлось бы подождать, пока она завершится, чтобы получить следующую подсказку (где вы можете fg или bg ваше фоновое задание).

В zsh, когда вы нажимаете Ctrl-Z в:

{cmd1 && cmd2 && cmd3}

Это приостанавливает работу всей группы (и перемещает ее в подоболочку). Однако, при возобновлении, команда приостановления, когда она заканчивается, установит $? на 20, независимо от статуса выхода, и я не думаю, что есть способ обойти это, так что в конечном итоге вы повторите то же самое (хотя в {cmd1 || cmd2} cmd2 будет выполнена после завершения команды, а не прямо на Ctrl-Z)).

2
27.01.2020, 20:41

Похоже на приостановку работающего в настоящее время компонента с gdb -p доказывает изящную паузу, в отличие от kill -STOP.

Таким образом, если вы знаете, что команда2 выполняется в данный момент, вы можете сделать:

gdb -p $(pgrep -f 'command2')

с другого терминала, чтобы приостановить, а затем выйти или продолжить GDB, чтобы возобновить работу.

1
27.01.2020, 20:41

Вы можете приостановить родительскую оболочку - интерактивную оболочку, в которой вы запускаете команды в:

Распечатать PID перед запуском команд, (или найти pid позже, см. ниже):

$ echo $$
1234

С другого терминала вы можете остановить весь список команд, приостановив интерактивную оболочку - список состоит из дочерних процессов интерактивной оболочки:

$ kill -STOP 1234

И продолжить список команд с:

$ kill -CONT 1234


Так как это важная часть вашего случая использования, что не требуется никаких приготовлений (например, echo $$) перед запуском списка команд, вот как вы получите PID оболочки, которую вы хотите остановить, когда список уже запущен на переднем плане.

Идея заключается в том, чтобы найти PID родительского процесса любой из команд в списке:

Сначала мы используем pgrep, чтобы найти PID текущей выполняемой команды. Поиска PID любой из них достаточно, так как одновременно выполняется только одна:

$ pgrep 'command1|command2|command3'

Если команда1 и т.д. на самом деле не является именем команды процесса - т.е. первым словом командной строки - нужно добавить опцию -f (и использовать -a для экспериментов, чтобы увидеть больше, чем просто PID):

$ pgrep -f 'command1|command2|command3'

Затем мы используем ps, чтобы найти родительский PID команды:

$ ps -o ppid= 

Комбинированный, мы получаем PID оболочки, чтобы приостановить так:

$ pid=$(ps -o ppid= $(pgrep 'command1|command2|command3'))

Всего:

$ kill -STOP $(ps -o ppid= $(pgrep 'command1|command2|command3'))
$ kill -CONT $(ps -o ppid= $(pgrep 'command1|command2|command3'))
0
27.01.2020, 20:41

Теги

Похожие вопросы