2015-04-14 4 views
-2

Примечание редактора: В конце концов, OP пытается упаковать код от this answer как скрипт. Указанный код создает открытый FIFO, из которого команда фона считывает данные для обработки по мере их поступления.Фоновый процесс, как представляется, висит

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

#!/bin/bash 
cat >a& 
pid=$! 

, кажется, что программа застревает в cat>a&

$pid не имеет значения после выполнения скрипта, но процесс cat, кажется, существует.

+1

Что вы пытаетесь кота? «a» будет пустым. – Prabhu

+1

Конечно, 'pid' не будет иметь значения * после выхода скрипта * - все переменные оболочки по своей природе исчезают, когда оболочка делает. Выходы сценария -> оболочка, выполняющая выходы сценария -> больше переменных. –

+0

@Prabhu Я пытаюсь написать сценарий для ответа в вопросе. он работает только в том случае, если я нахожу его в конце строки по строке http://serverfault.com/questions/443297/write-to-stdin-of-a-running-process-us%E2%80%8C%E2%80% 8Bing-pipe% 20- – user3472537

ответ

1

Вам необходимо указать файл с «кошкой»:

#!/bin/bash 
cat SOMEFILE >a & 
pid=$! 
echo PID $pid 

Хотя это кажется немного глупым - почему бы не просто «ср» файл (cp SOMEFILE a)?

В: Чего именно вы пытаетесь достичь?

+1

Преимущество состоит в том, что вы можете конкатрировать несколько файлов с 'cat', но не с' cp'. Просто говорю. – 4ae1e1

+1

О, еще одна вещь, которую вы не можете сделать с 'cp': вы можете использовать символьные устройства' cat', например '/ dev/null'. (Просто указывая на очевидное.) – 4ae1e1

+1

Следуя ссылке OP - 'a' является FIFO, что делает причиной не использования' cp' clear. –

2

Причина, по которой cat >a «зависает», заключается в том, что она считывает из стандартного потока ввода (stdin, дескриптор файла нуль), который по умолчанию соответствует клавиатуре.

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

EDIT: хотя я и следовал за ссылкой в ​​вопросе, первоначально не было указано, что OP фактически использовал FIFO на этом этапе. Так спасибо @ mklement0.

Я не понимаю, что вы пытаетесь сделать здесь, но я подозреваю, что вам нужно, чтобы запустить его в качестве «соерсед» файл следующим образом:

. gash.sh 

Где gash.sh это имя вашего сценария , Обратите внимание на предшествующее .

+0

Я думаю, вы ударили гвоздь на голову относительно необходимости * источника * сценария. Тем не менее, я подозреваю, что «зависание» происходит не от команды 'cat' (что состояния OP выполняются с' & 'даже в интерактивном режиме), а из последующей попытки записать в _FIFO_' a', у которого другой конец никто больше не слушает, из-за выхода сценария (я заполнил недостающие части из связанного вопроса serverfault.com). – mklement0

+1

@ mklement0: совершенно. – cdarke

2

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 
+1

Хорошее продолжение – cdarke

Смежные вопросы