пернаправление ввода

На самом деле это единственный раздел про unix на этом форуме

Модератор: /dev/random

v4567
Сообщения: 109

пернаправление ввода

Сообщение v4567 » 29.07.2017 14:27

Есть скрипт на BASH, в котором я перехватываю сигналы:

Код: Выделить всё

# Перехватываем сигналы.
 # Завершение работы, сигнал "TERM".
 trap 'vozvrisxzn ; exit 0' SIGTERM
 # Завершение работы, сигнал посланный комбинацией клавиш Ctrl+c.
 trap 'vozvrisxzn ; exit 0' SIGINT
 # Отправка в фон - нажатие Ctrl+z.
 trap 'vozvrisxzn' SIGTSTP
 # Возврат из фона - набор в консоли bg или fg.
 trap 'izfona' SIGCONT
 # Изменение размеров терминала во время работы программы.
 trap 'izmrazmterm' SIGWINCH


Этот код стоит в начале скрипта. Далее после некоторого выполнения скрипта (он выводит некоторую информацию в терминал) он останавливается и ждёт нажатия клавиш командой read. Если вместо read сделать бесконечный пустой цикл, то сигналы обрабатываются сразу. Например после изменения размеров графического эмулятора терминала, выведенная информация отлично подстраивается под изменившиеся размеры терминала.
Когда же мы ждём нажатия клавиш командой read, то после изменения размеров терминала обработка этого сигнала происходит только тогда когда мы нажмём какую нибудь клавишу, то есть только тогда когда отработает команда read. Получается, что обработка сигналов происходит только после окончания выполнения команды во время которой пришёл сигнал.
Поставить маленькое время ожидания read (например -t 0.5 секунд) я не могу, мне же надо что бы сигналы обрабатывались сразу или хотя бы с маленькой задержкой, но не после тога как я нажму на клавишу.
Вариант вижу только один (да и то я не уверен что это можно сделать), read сделать в отдельной функции например fynk() и эту функцию запускать в фоне. Получится так что запуститься дополнительный экземпляр bash с этой функцией, его pid я могу узнать, получаем вот такой код:

Код: Выделить всё

fynk &
PIDFYNK=$!


Теперь вопрос и трудность вот в чём, можно ли как то перенаправить ввод с клавиатуры то есть перенаправить стандартный входной поток (дескриптор файла 0) в этот процесс, функцию fynk и команду в этой функции read? Если можно то как это сделать?

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

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

За помощь буду заранее благодарен!
Спасибо сказали:

Аватара пользователя
/dev/random
Администратор
Сообщения: 4748
ОС: Gentoo

Re: пернаправление ввода

Сообщение /dev/random » 30.07.2017 00:41

1) У меня и с read всё прекрасно работает:

$ ( trap 'echo hello' SIGWINCH; read ) (меняю размер терминала) hello hello hello hello hello hello



2) Если вы запустите read в фоне, у вас будут проблемы с получением данных из него. Изменение переменной в одном сабшелле не вызывает её изменения в другом. Вам придётся передавать данные через пайпы, т.е. всё через тот же read.

3) Ну и всё-таки отвечу на ваш вопрос, хоть ответ на него и не решит вашу проблему. Чтобы разрешить фоновому процессу читать из stdin основного, нужно переадресовать ввод явным образом: cmd <&0 &
Спасибо сказали:

v4567
Сообщения: 109

Re: пернаправление ввода

Сообщение v4567 » 02.08.2017 19:17

Если использовать просто read то работает.

Но у меня вот такая конструкция:

Код: Выделить всё

while [ true ]
  do

    KEY=""
    zaderjka=""

    for (( i=0 ; i<10 ; i++ ))
     do
       eval $( (IFS="" read -r -s -n 1 $zaderjka key ; printf 'code %d' "'$key") 2>&1 | awk 'NR==1||NR==4 {print $1 "=" $2}' )
       if [ "$code" != "0" ] || [ "$code" = "0" -a "$zaderjka" = "" ]
        then
            KEY=$KEY$code
       fi
       zaderjka="-t 0.01"
    done
done


Вот с такой конструкцией всё останавливается и ждёт нажатия клавиши.

На другом форуме подсказали вот такую конструкцию:

Код: Выделить всё

while [ true ]
  do

    KEY=""
    zaderjka=""

    for (( i=0 ; i<10 ; i++))
     do
       code=""
       IFS="" read -r -s -n 1 $zaderjka key && printf -v code '%d' "'$key"
       [ -n "$code" ] && KEY=$KEY$code
       zaderjka="-t 0.01"
    done
done


При такой конструкции всё нормально, почему при первой останавливалось я так и не понял.


Спасибо за:

Код: Выделить всё

cmd <&0 &


Проверил, работает.
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 15050
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: пернаправление ввода

Сообщение Bizdelnick » 02.08.2017 21:06

v4567 писал(а):
02.08.2017 19:17
почему при первой останавливалось я так и не понял.

Ждало завершения сабшелла, который ждал завершения другого сабшелла.
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
/dev/random
Администратор
Сообщения: 4748
ОС: Gentoo

Re: пернаправление ввода

Сообщение /dev/random » 02.08.2017 22:04

iУведомление от модератора
Второй вопрос отрезан в отдельную тему: Просмотр чужого терминала
Спасибо сказали:

v4567
Сообщения: 109

Re: пернаправление ввода

Сообщение v4567 » 03.08.2017 12:08

Ждало завершения сабшелла, который ждал завершения другого сабшелла.


Сабшеллы - это $() и eval?
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 15050
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: пернаправление ввода

Сообщение Bizdelnick » 03.08.2017 12:48

$() и ()
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали: