Захват ввода пользователем при выполнении других действий

Есть ли способ, чтобы выход подпроцесса (что-то вроде «сна») был согласован с выходом из командного цикла foreground? Например:

while true do echo "updating screen..." sleep 3 & # Replace with command which takes some time and updates the screen read -s -n 1 -p "Input: " input case "$input" in q) exit ;; f) echo 'foo' ;; esac done 

  • Как подключить stdout к файлу, если текущая команда уже передается через gzip
  • Установка переменной со значением по умолчанию ведет себя по-другому, если перед командой?
  • Сбросьте шаблон слова в конце строки, используя sed
  • Сколько снарядов я глубоко?
  • удалите строки, которые новее, чем заданная дата в файле
  • Как сделать bash glob строковой переменной?
  • запуск vim с заменой команды
  • Bash для преобразования всех файлов определенного типа из Unix в формат Dos
  • Пропустить первую строку (или больше) в CSV-файле, который используется для переименования файлов
  • Начисление PS1 асинхронно
  • В чем разница между поиском ('.' Или 'source') и выполнением файла в bash?
  • Ключ от Unix User Level
  • One Solution collect form web for “Захват ввода пользователем при выполнении других действий”

    Оболочка делает предположения о многопроцессорности; первая и самая важная: одна программа должна контролировать терминал за раз, иначе вход (и выход) будет запутан. Что делать, если программа, которую вы ставите вместо «сна», хочет получить вход от терминала? Где посылается ввод с клавиатуры? К подпроцессу («sleep») или к инструкции read ?

    Из этого вы должны предположить, что подпроцесс («sleep») не будет вводиться. Вам также нужно подождать, пока не закончатся оба командных цикла (обработка «q» или «f») и подпроцесс. Я бы посоветовал написать это нечто иное, чем скрипт оболочки, например, python, чтобы обойти предположения оболочки; но, как я покажу, это можно сделать в оболочке Bourne (или ksh или bash или zsh).

     #!/usr/bin/python import os, select, subprocess, sys devnull = open('/dev/null', 'a') # this is the same as "sleep 3 </dev/null > pipefile &" but will handle # processing output at the same time p = subprocess.Popen( ['/bin/sh', '-c', 'i=0; while [ $i -lt 30 ]; do echo $i; sleep 2; i=`expr $i + 1`; done' ], stdin=devnull, stdout=subprocess.PIPE, stderr=subprocess.STDOUT ) command_done = False try: # endless loop until both input and output are done while True: inputs = [] # only send input to our command loop if not command_done: sys.stdout.write('Input: ') sys.stdout.flush() inputs.append(sys.stdin) if p.returncode is None: # still not finished p.poll() inputs.append(p.stdout) outputs = [] if not inputs and not outputs: # both are done break # exit while loop #print inputs, outputs r, w, x = select.select(inputs, outputs, []) #print 'r=', r, 'w=', w, 'x=', x # input from the user is ready for file in r: if file is sys.stdin: input = file.read(1) if input == 'q': command_done = True if p.returncode is None: os.kill(p.pid, 15) elif input == 'f': sys.stdout.write('foo\n') # the subprocess wants to write to the terminal too else: input = file.readline() sys.stdout.write(input) finally: if p.poll(): try: print os.kill(p.pid, 15) except OSError: pass 

    Вы можете сделать это в сценарии оболочки, но вход / выход не будут столь же хорошо интегрированы.

     #!/bin/bash mkfifo /tmp/mergedout.p ( i=0; while [ $i -lt 30 ]; do echo $i; sleep `expr 30 - $i`; i=`expr $i + 1`; done ) </dev/null >/tmp/mergedout.p 2>&1 & pid=$! exec 3</tmp/mergedout.p done=false trap 'rm /tmp/mergedout.p' 0 while [ -n "$pid" -a $done = false ]; do if [ $done = false ]; then echo -n "Input: " read -t 0.1 -s -r -n 1 case $REPLY in q) done=true; if [ -n "$pid" ]; then kill $pid; fi;; f) echo foo;; esac fi if [ -n "$pid" ]; then kill -0 $pid 2>&- if [ $? -ne 0 ]; then echo "$pid terminated" wait $pid pid="" exec 3<&- else read -t 0.1 -u 3 -r echo "reading from fd3: X${REPLY}X $?" if [ -n "$REPLY" ]; then echo "$REPLY" fi fi fi sleep 0.5 done 

    Сам, питон немного более ясен и более «согласован», но по большей части это можно сделать в любом случае.

    Linux и Unix - лучшая ОС в мире.