Как читать stderr из процесса, работающего в фоновом режиме?

У меня работает следующее:

STYLUS_ID=11 # replace with ID or name of your stylus
TOUCH_ID=9 # replace with ID or name of your touch screen

xinput test -proximity "$STYLUS_ID" |
    while read line; do
        if [[ $line == *out* ]]; then
            xinput enable "$TOUCH_ID"
        else
            xinput disable "$TOUCH_ID"
        fi
    done

Вместо опроса состояния стилуса, он полагается на опцию test из xinput, которая входит в бесконечный цикл отображения proximity событий для устройства. Из руководства xinput:

    test [-proximity] device
           Register all extended events from device and enter an endless loop
           displaying events received. If the -proximity is given, ProximityIn
           and ProximityOut are registered.
0
29.05.2019, 19:27
2 ответа

mkfifoможет делать то, что вам нужно. Смотрите этот ответ :https://stackoverflow.com/questions/43949166/reading-value-of-stdout-and-stderr

Use a FIFO Instead

Technically, /dev/stdout and /dev/stderr are really file descriptors, not FIFOs or named pipes. On my system, they're actually just symlinks to /dev/fd/1 and /dev/fd/2. Those descriptors are typically linked to your TTY or PTY. So, you can't really read from them the way you're trying to do.

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

fifo="daemon_errors"
{
    mkfifo $fifo
    for x in {1..9}; do
        sleep 1
        if [ "$x" != "5" ]; then
            echo $x 1>&2
        else
            echo now 1>&2
        fi
    done 2>$fifo
} &

sleep 1 # need to wait until the file is created

# Read all output 
while read -r line; do
    echo "just read: $line"
done < $fifo
0
28.01.2020, 03:39

Другие ответы включают использование файлов или именованных каналов. Вам тоже не нужно. Достаточно простой трубы.

#!/bin/bash

run_daemon() {
    # Fictional daemon
    {
        for x in {1..9}; do
            sleep 1
            if [ "$x" != "5" ]; then
                echo $x 1>&2
            else
                echo now 1>&2
            fi
        done
    }
}

run_daemon 2>&1 | (

    exec 9<&0 0</dev/null

    while read -u 9 line && test "$line" != now
    do
        echo "$line"    ## or ## :
    done
    echo "$line"        ## or ##
    cat /dev/fd/9 &     ## or ## cat /dev/fd/9 >/dev/null &

    #fictional stuff
    for a in 1 2 3
    do
        echo do_stuff $a
        sleep 1
    done
    echo done

    wait
)

Разделы, помеченные ## or ##, являются альтернативой, если вы не хотите показывать смешанный вывод демона. Обратите внимание, что вы не можете опустить кошку, потому что это единственное, что мешает демону получить SIGPIPE при выводе.

Я пробовал не перенаправлять ввод на другой файловый дескриптор (на exec), но без этого что-то закрывает ввод и демон завершает работу.

Вы также можете заметить, что демон явно не фоновый. С трубой он не нужен. waitждет кота, а не демона. Это все еще работает, если демон находится в фоновом режиме.

waitаналогичен fg, но не дает консольному управлению. (Он также намного старше.)

0
04.10.2020, 12:46

Теги

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