Создайте аббревиатуру для «2> / dev / null &»

Для самого фона это приложение создает дочерний процесс и закрывает родительский. Оболочка знает о родительском процессе как о том, который она разветвила перед выполнением самой команды, но она не видит потомков или внуков, которые могли быть порождены этим процессом.

Более простой пример такой фоновой команды:

$ sh -c 'ps -j; sleep 10 &'
  PID  PGID   SID TTY          TIME CMD
 6562  6562 14469 pts/13   00:00:00 sh
 6563  6562 14469 pts/13   00:00:00 ps
14469 14469 14469 pts/13   00:00:00 zsh

Мой zsh знает об этом процессе sh и его группе процессов.

Однако он видит только то, что процесс 6562 завершается. У него нет возможности узнать, что процесс 6562 породил процесс 6563.

$ ps -j
  PID  PGID   SID TTY          TIME CMD
 6564  6562 14469 pts/13   00:00:00 sleep
 6565  6565 14469 pts/13   00:00:00 ps
14469 14469 14469 pts/13   00:00:00 zsh

Однако вы можете видеть, что запущенный процесс sleep также находится в этой группе процессов 6562 (хотя нет ничего, что останавливает команды, запускающие новые группы процессов или даже сеансы (как обычно делают демоны)).

Эти группы процессов создаются только тогда, когда оболочка интерактивна.

Еще вы могли бы сделать следующее:

cmd | cat &
wait

Если процессы, порождаемые cmd, не закрывают свой стандартный вывод, тогда cat не умирает, пока все они не умрут.

0
03.05.2018, 16:02
2 ответа

В настоящее время вы указываете своему сценарию обрабатывать каждый параметр как отдельное приложение. Итак, вы бежите:

$ vlc

Тогда:

$ video.mp4

Вы должны сделать свой сценарий более похожим на этот:

#!/bin/bash
$@ 2>/dev/null

Что, на мой взгляд, лучше подошло бы в качестве функции:

func_name() {
$@ 2>/dev/null
}

Обратите внимание, :это позволит вам запускать только одну команду за раз. Я не уверен, что вашим первоначальным намерением было передать несколько команд одновременно вашему сценарию, если это так, я удалю.

1
28.01.2020, 02:15

Есть две проблемы:

  1. Использование $@без кавычек.

    Это заставит цикл перебирать vlcи video.mp4как два отдельных элемента, даже если они находятся в одной и той же строке в кавычках при вызове скрипта.

  2. Использование команды в переменной.

    Если команда представляет собой нечто более сложное, чем одна простая команда, то это не сработает. Вместо этого вам нужно будет evalуказать данную строку.

Принимая это во внимание, ваш скрипт может выглядеть так

#!/bin/sh

for cmd do  # or:  for cmd in "$@"; do
    eval "$cmd" 2>/dev/null
done

Вызов этого как

./script 'echo "hello world"' 'vim "$HOME/.profile"' 'tr a-z A-Z <"$HOME/.profile" | grep -c EXPORT'

сначала запустит echo "hello world", а когда это завершится, откроется vimдля редактирования именованного файла в этой второй команде. Последняя команда более сложная, но обрабатывается тем фактом, что мы используем eval(, она просто изменяет все буквы алфавита на прописные и подсчитывает, сколько раз строка EXPORTвстречается в файле ). Он запускается сразу после завершения сеанса vim.

С этим можно даже сделать

./script 'd=$HOME' 'ls "$d"'

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

5
28.01.2020, 02:15

Теги

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