cdarke's answer содержит важный указатель: ваш сценарий не должен работать в процессе ребенок, так что вы должны источник это.
Основываясь на вопрос, который вы связаны, это звучит, как вы пытаетесь сделать следующее:
- Открыть в FIFO (именованный канал).
- Храните этот FIFO открытым на неопределенный срок.
- Сделайте команду , считываемую из этого FIFO всякий раз, когда к нему отправляются новые данные.
См. Нижнюю часть рабочего решения.
Как для объяснения ваших симптомов:
Запуск сценария НЕ Sourced (НЕ с .
) означает, что скрипт работает в процессе ребенка, который имеет следующие последствия:
- Переменная s, определенные в скрипте, видны только внутри этого скрипта, и переменные вообще перестают существовать, когда скрипт заканчивается.
- Именно поэтому вы не увидели переменную сценария
$myPid
после запуска сценария.
- Когда сценарий завершает работу, его фоновые задачи (
cat >a&
) убивают (как cdarke объясняет, то SIGHUP
сигнал посылается к ним, любой процесс, который не явно ловушка, что сигнал прекращается).
- Это противоречит вашей претензии, что процесс
cat
продолжает существовать, но я думаю, что вы перепутали в интерактивно начали cat
процесс, который запускается с помощью сценария.
В противоположность этому, любой FIFO создается скриптом (с mkfifo
) делает сохраняются после выхода скрипта (ФИФО ведет себя как файл - она сохраняется, пока вы явно не удалите его).
- Однако когда вы написать к этому FIFO без другого процесса чтения из него, команды писать будет блок и, таким образом, появляются дотянуть (в пишущих процесс блокирует до другого процесс читает данные из FIFO).
- Возможно, это произошло в вашем случае: поскольку фоновые процессы сценария были убиты, никто не читал из FIFO, что вызвало попытку записать его для блокировки. Вы ошибочно предположили, что это была команда
cat >a&
, которая «застревала».
Следующий сценарий, когда источников, добавляет функции к текущей оболочки для настройки и очистки на пребывание открытой FIFO с командой фона, который обрабатывает данные по мере их поступления.Сохраните его как файл bgfifo_funcs
:
#!/usr/bin/env bash
[[ $0 != "$BASH_SOURCE" ]] || { echo "ERROR: This script must be SOURCED." >&2; exit 2; }
# Set up a background FIFO with a command listening for input.
# E.g.:
# bgfifo_setup bgfifo "sed 's/^/@ /'"
# echo 'hi' > bgfifo # -> '@ hi'
# bgfifo_cleanup
bgfifo_setup() {
(($# == 2)) || { echo "ERROR: usage: bgfifo_setup <fifo-file> <command>" >&2; return 2; }
local fifoFile=$1 cmd=$2
# Create the FIFO file.
mkfifo "$fifoFile" || return
# Use a dummy background command that keeps the FIFO *open*.
# Without this, it would be closed after the first time you write to it.
# NOTE: This call inevitably outputs a job control message that looks
# something like this:
# [1]+ Stopped cat > ...
{ cat > "$fifoFile" & } 2>/dev/null
# Note: The keep-the-FIFO-open `cat` PID is the only one we need to save for
# later cleanup.
# The background processing command launched below will terminate
# automatically then FIFO is closed when the `cat` process is killed.
__bgfifo_pid=$!
# Now launch the actual background command that should read from the FIFO
# whenever data is sent.
{ eval "$cmd" < "$fifoFile" & } 2>/dev/null || return
# Save the *full* path of the FIFO file in a global variable for reliable
# cleanup later.
__bgfifo_file=$fifoFile
[[ $__bgfifo_file == /* ]] || __bgfifo_file="$PWD/$__bgfifo_file"
echo "FIFO '$fifoFile' set up, awaiting input for: $cmd"
echo "(Ignore the '[1]+ Stopped ...' message below.)"
}
# Cleanup function that you must call when done, to remove
# the FIFO file and kill the background commands.
bgfifo_cleanup() {
[[ -n $__bgfifo_file ]] || { echo "(Nothing to clean up.)"; return 0; }
echo "Removing FIFO '$__bgfifo_file' and terminating associated background processes..."
rm "$__bgfifo_file"
kill $__bgfifo_pid # Note: We let the job control messages display.
unset __bgfifo_file __bgfifo_pid
return 0
}
Затем источник скрипт bgfifo_funcs
, используя встроенную команду .
оболочки:
. bgfifo_funcs
Sourcing выполняет сценарий в тока оболочки (а не в дочерний процесс, который завершается после запуска сценария), и, таким образом, функции и переменные скрипта доступны для текущей оболочки. Функции по определению запускаются в текущей оболочке, поэтому любые фоновые команды, запущенные из функций, остаются в силе.
Теперь вы можете настроить пребывания открытой ФИФО с фоновым процессом, который обрабатывает входные данные как он поступает следующим образом:
# Set up FIFO 'bgfifo in the current dir. and process lines sent to it
# with a sample Sed command that simply prepends '@ ' to every line.
$ bgfifo_setup bgfifo "sed 's/^/@ /'"
# Send sample data to the FIFO.
$ echo 'Hi.' > bgfifo
@ Hi.
# ...
$ echo 'Hi again.' > bgfifo
@ Hi again.
# ...
# Clean up when done.
$ bgfifo_cleanup
Что вы пытаетесь кота? «a» будет пустым. – Prabhu
Конечно, 'pid' не будет иметь значения * после выхода скрипта * - все переменные оболочки по своей природе исчезают, когда оболочка делает. Выходы сценария -> оболочка, выполняющая выходы сценария -> больше переменных. –
@Prabhu Я пытаюсь написать сценарий для ответа в вопросе. он работает только в том случае, если я нахожу его в конце строки по строке http://serverfault.com/questions/443297/write-to-stdin-of-a-running-process-us%E2%80%8C%E2%80% 8Bing-pipe% 20- – user3472537