Получить PID команды в однострочном скрипте bash [дубликат]

Вопрос или проблема

При попытке получить PID оболочки команды это возможно с помощью скрипта:

#!/bin/bash

ls -lha &
echo "$!"

Однако это невозможно использовать только терминал.

/bin/bash -c 'ls -lha & ; echo "$!"'

Это приводит к ошибке:

/bin/bash: -c: строка 1: синтаксическая ошибка рядом с неожиданным токеном `;’

Руководство гласит следующее:

Список — это последовательность из одной или нескольких конвейеров, разделенных одним из операторов ;, &, && или ||, и по желанию заканчивается одним из ;, & или <новая строка>.
Из этих операторов списков && и || имеют равный приоритет, за ними следуют ; и &, которые тоже имеют равный приоритет.

Последовательность из одной или нескольких новых строк может появляться в списке вместо точки с запятой для разделения команд.

Если команда заканчивается оператором управления &, оболочка выполняет команду в фоновом режиме в подсистеме.
Оболочка не ждет завершения команды, и возвращаемый статус равен 0.
Команды, разделенные ;, выполняются последовательно; оболочка ждет завершения каждой команды по очереди.
Возвращаемый статус — это выходной статус последней выполненной команды.

Я также пытался использовать новую строку, но не смог сделать это:

/bin/bash -c 'ls -lha & \n echo "$!"'

Как я могу вызвать команду оболочки для выполнения в фоновом режиме и получить PID?

П.С.: Я не буду использовать команду ls, это более сложный скрипт.
Это всего лишь минимальный пример, чтобы воспроизвести проблему.

И ;, и & являются разделителями команд.
Вам нужен один, чтобы отделить команду ls от команды echo, но не оба.
Просто уберите ; и сделайте

/bin/bash -c 'ls -lha & echo "$!"'

Если хотите, можете добавить реальную новую строку:

/bin/bash -c 'ls -lha &
echo "$!"'

или используйте $'…':

/bin/bash -c $'ls -lha & \n echo "$!"'

Конечно, вам нужно иметь разделители команд между командами; один между каждыми двумя последовательными командами.
Так что, если вы хотите, скажем, четыре команды, где первая асинхронная, а остальные синхронные, вам нужно использовать

             команда1 & команда2; команда3; команда4

Ответ или решение

Для получения PID (идентификатора процесса) команды в одной строке Bash-скрипта, необходимо правильно использовать оператор & для запуска команды в фоновом режиме и обеспечить корректное использование разделителей команд. Основная проблема, связанная с ошибкой синтаксиса, возникает из-за неправильного размещения операторов.

Решение проблемы

Для запуска команды и получения её PID в одной строке вы можете использовать следующий вариант:

/bin/bash -c 'ls -lha & echo "$!"'

Эта строка работает следующим образом:

  1. ls -lha & – запускает команду ls -lha в фоновом режиме. Оператор & сообщает оболочке, что команда должна быть выполнена в фоне.
  2. echo "$!" – выводит PID последнего запущенного фонового процесса. Переменная $! содержит идентификатор процесса последней команды, выполненной в фоновом режиме.

Альтернативные способы

Если вы предпочитаете использовать новую строку, то в качестве разделителя можно использовать следующий подход:

/bin/bash -c 'ls -lha &
echo "$!"'

Либо, используя формат $'...', который позволяет явно включать управляющие символы, такие как новая строка:

/bin/bash -c $'ls -lha &\necho "$!"'

Применение в более сложных скриптах

Если ваш скрипт включает в себя большее количество команд, где одна из них выполняется асинхронно, вы можете организовать код следующим образом:

command_1 & command_2; command_3; command_4

Где command_1 выполняется в фоновом режиме, а command_2, command_3 и command_4 выполняются последовательно, дожидаясь завершения предыдущей команды.

Заключение

Важно понимать, что правильное использование разделителей команд и работу с фоновыми процессами необходимо для успешного выполнения задач в Bash. Приведенные решения позволяют вам легко получать PID команды, запущенной в фоновом режиме, и будут работать для различных сценариев выполнения более сложных скриптов.

Оцените материал
Добавить комментарий

Капча загружается...