Как команда может иметь больше чем один вывод?

Ваш kill команда назад.

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

Если Вы пишете

kill -INT 0

это видит -INT как опция, и отправляет SIGINT кому: 0 (0 специальное число, означающее все процессы в группе текущего процесса).

Но если Вы пишете

kill 0 -INT

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

kill -TERM 0 -INT    

(это также попыталось бы отправить SIGTERM кому: -INT, который вызвал бы синтаксическую ошибку, но она отправляет SIGTERM кому: 0 во-первых, и никогда не получает это далеко.)

Таким образом, Ваш основной сценарий получает a SIGTERM прежде чем это доберется для выполнения wait и echo DONE.

Добавить

trap 'echo got SIGTERM' TERM

наверху, сразу после

trap 'killall' INT

и выполненный это снова для доказательства этого.

Как Stephane Chazelas указывает, Ваши второстепенные дети (process1, и т.д.), проигнорирует SIGINT по умолчанию.

В любом случае я думаю, отправляя SIGTERM имел бы больше смысла.

Наконец, я не уверен ли kill -process group как гарантируют, перейдет к детям сначала. Игнорирование сигналов, в то время как закрытие могло бы быть хорошей идеей.

Так попробуйте это:

#!/bin/bash
trap 'killall' INT

killall() {
    trap '' INT TERM     # ignore INT and TERM while shutting down
    echo "**** Shutting down... ****"     # added double quotes
    kill -TERM 0         # fixed order, send TERM not INT
    wait
    echo DONE
}

./process1 &
./process2 &
./process3 &

cat # wait forever
5
13.04.2017, 15:36
3 ответа

cat foo bar пример не то, что я имел в виду. Здесь cat только имеет вход того и один вывод за один раз.

tee пример: это производит ко всем аргументам плюс его стандартный вывод одновременно. Используя тот же вид схемы ASCII-творчества как в моем предыдущем ответе, вот то, как tee foo bar похож, когда это работает в терминале.

   +------------------+    
   |       tee        |    
===|<stdin            |         +------------+
→  |                  |         |  terminal  |
   |           stdout>|=========|<input      |
   |                  |   → ##==|<           |
   |                  |     ||  +------------+
   |           stderr>|=====##
   |                  |   →
   |                  |       +-------------+
   |                3>|=======|> file "foo" |
   |                  |   →   +-------------+
   |                  |       +-------------+
   |                4>|=======|> file "bar" |
   |                  |   →   +-------------+
   |                  |    
   +------------------+    

В этом примере, tee отправляет “полезный” вывод на три канала: к терминалу (потому что это - то, где его стандартный вывод подключен с), и в два файла. Кроме того, tee имеет еще один канал вывода для ошибок.

Программа обычно имеет три канала ввода-вывода, определенные их числом дескриптора файла:

  • стандартный вход (stdin, если коротко, дескриптор файла номер 0);
  • стандартный вывод (stdout, если коротко, дескриптор файла номер 1);
  • стандартная погрешность (stderr, если коротко, дескриптор файла номер 2).

Целью дескрипторов файлов 0, 1 и 2 является только вопрос конвенции — ничто не осуществляет это, программа не может попытаться записать в дескриптор файла 0 или читать из дескрипторов 1 и 2 — но это - конвенция, которая в значительной степени универсально сопровождается.

Если Вы запускаете программу от терминала, дескрипторы файлов 0, 1 и 2 начинаются подключенный к тому терминалу, если они не были перенаправлены. Другие дескрипторы файлов начинаются закрытый и будут использоваться, если программа открывает другие файлы.

В частности, все команды имеют два вывода: стандартный вывод (для полезной нагрузки команды, “полезного” вывода), и стандартная погрешность (для ошибки или информационных сообщений).

Конвейер в оболочке (command1 | command2 | command3 | …) подключения стандартный вывод каждой команды к стандартному входу следующей команды. Стандартная погрешность всех команд переходит к терминалу (если не перенаправлено).

Оболочки обеспечивают способы перенаправить другие дескрипторы файлов. Вы, вероятно, встретились 2>&1 или 2>file перенаправить стандартную погрешность. Посмотрите при использовании дополнительного дескриптора файла? и другие сообщения это связывается с для примеров манипуляций другими дескрипторами файлов.

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

Очень немного команд пытаются получить доступ к дескрипторам файлов выше 2, кроме того, после того, как они открылись, файл (открывающий файл выбирает свободный дескриптор файла и возвращает его число приложению). Одним примером является GnuPG, который ожидает считывать данные, чтобы зашифровать/дешифровать/подписать/проверить на его стандартном входе и записать результат в стандартный вывод. Этому можно сказать считать пароль на другом дескрипторе файла с --passphrase-fd опция. GnuPG также имеет опции сообщить о данных состояния по другим дескрипторам файлов, таким образом, можно было произвести полезную нагрузку на stdout, сообщениях об ошибках на stderr и информации о статусе о другом дескрипторе файла. Вот пример, где вывод переданной по каналу команды используется в качестве пароля:

echo fjbeqsvfu | rot13 | gpg -d --passphrase-fd=3 3<&0 <file.encrypted >file.plaintext
9
27.01.2020, 20:32

Да. Например, cat foo bar | less дает два исходных данные (нечто файла и панель файла) и производит их обоих к меньше. vim foo* произведет все файлы, начинающиеся с нечто в энергию. После рассмотрения каждого файла можно затем переключиться на следующий вывод с: n (или: wn, если Вы изменили что-нибудь). Я думаю, что Gilles объяснил это очень хорошо. При использовании канала (|), он берет вывод одной команды, вводит его в другую команду и затем производит результат. Это - другой пример нескольких выводов.

3
27.01.2020, 20:32
  • 1
    , но это - все еще один вывод для каждого процесса. если это не то, что имел в виду Gilles. Я думаю, что это - действительно вопрос о формулировке, таким образом, я спрошу относительно исходного ответа. –  strugee 19.10.2013, 09:01
  • 2
    Корректный. Существует только один вывод для каждого процесса. Если я сделал find . -name "*.bak" -type f -print | xargs /bin/rm -f Это ввело бы много файлов, передало бы аргументы по каналу xargs и затем произвело бы каждый процесс. –  Jeight 19.10.2013, 09:03
  • 3
    @Jeight, Ваш ответ корректен, но это не то, что я имел в виду. Я обращался к нескольким одновременным вводам или выводам. Все команды действительно имеют два вывода, между прочим: stdout и stderr. Примечание –  Gilles 'SO- stop being evil' 20.10.2013, 04:09

Команды могут иметь больше чем один поток вывода, и я не подразумеваю под записью в файлы или сокеты. Рассмотрите большинство инструментов GNU (например. grep) та печать ошибки к stderr и ожидаемый вывод к stdout. В то время как в интерактивной оболочке оба объединяются (2> &1), можно все еще рассматривать их отдельно. Это не заканчивается там, так как можно использовать дополнительные дескрипторы файлов, если программа или блок кода поддерживают его.

Изобретенный пример:

{
  grep NORMAL log.txt
  grep WARN log.txt 1>&3
  grep ERROR log.txt 1>&4
} 1> normals.txt 3> warnings.txt 4> errors.txt # 2>/dev/null
3
27.01.2020, 20:32

Теги

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