2013-02-20 1 views
2

У меня довольно странная проблема. Я не могу понять, почему это происходит или как это исправить.Команда не дает выхода при чтении?

Сценарий:

#!system/bin/sh 
#set -x 

reader() { 
    t2=-1 
    grep -v -E "add device|name:" | while IFS=' ' read -r t1 a b c d _; do 
     t1=${t1%%-*} 
     t=`expr $t1 - $t2` 
     if let 't > 0 && t2 > -1'; then 
      echo "sleep $t" 
     fi 
     printf 'sendevent %s' "${a%?}" 
     printf '%5d %5d %5d\n' "0x$b" "0x$c" "0x$d" 
     t2=$t1 
    done 
} 

let() { 
    IFS=, command eval [ '$(($*))' -ne 0 ] 
} 

countDown() { 
    echo 'Starting in...' 
    i=4 
    while [[ $i -gt 1 ]]; do 
     i=$(($i-1)) 
     echo "$i" 
     sleep 1 
    done 
    printf '%s\n\n\n' 'Go!' 
# echo "$*" 
    "[email protected]" | reader 
} 

clear 
printf '%s >' 'Catch by [n]umber of events or [t]imeout?' 
read type 

case $type in 
    n) 
     printf '%s >' 'Events to catch?' 
     read arg 
     echo "Gonna catch $arg events!" 
     countDown getevent -t -c "$arg" 
     ;; 
    t) 
     printf '%s >' 'Timeout (in seconds)?' 
     read arg 
     echo "Gonna catch events for $arg seconds!" 
     countDown timeout -t $arg getevent -t 
esac 

Цель сценария:

Поймайте взаимодействия пользователя (например, нажатие клавиши, экран краны и т.д.) с помощью команды GetEvent и выводит скрипт на stdout, который может использоваться для репликации этих событий.

Дополнительная информация: выход

GetEvent находится в шестнадцатеричном формате SendEvent принимает десятичный формат

Ожидаемый выход:

Catch by [n]umber or by [t]imeout? n 
Events to catch? > 4 
Gonna catch 4 events... 
Starting in... 
3 
2 
1 
Go! 
sendevent /dev/input/event5 1 102 1 
sendevent /dev/input/event5 0 0 0 
sleep 3 
sendevent /dev/input/event5 1 102 0 
sendevent /dev/input/event5 0 0 0 

Проблема:

Трассы код как expe cted, когда выбрано «n». Когда выбрано «t», сценарий завершается через указанное количество секунд. Однако он ничего не выводит - первая строка цикла while даже не запускается.

с множеством -x, вот то, что показано (последние несколько строк):

+ printf %s\n\n\n Go! 
Go! 
+ reader 
+ t2=-1 
+ grep -v -E add device|name: 
+ timeout -t 5 getevent -t 
+ IFS = read -r t1 a b c d _ 

Running это само по себе показывает вывод на стандартный вывод (вывод, который должен быть считан и изменен внутри цикла While):

timeout -t 5 getevent -t 

Любые идеи?

Спасибо.

EDIT:

Хорошо, так что я думаю, что это проблема с буферизацией. В основном это дает аналогичную проблему: getevent > output Файл обновляется каждый куча событий, но не мгновенно (и, возможно, никогда не обновится, если не будет сделано достаточно событий). Я не знаю, как работать на Android.

+0

Отключить тему для SO. Попробуйте XDA Devs – Simon

+0

@Simon Как это не в тему? Он может использовать специальные команды для Android, но это вопрос программирования, учитывая проблему, с которой я сталкиваюсь. – GermainZ

+0

Извините, я не могу помочь в этом конкретном битке arcana, но +1 для хорошо оформленного вопроса, показывающего значительную работу. Продолжайте публикацию. Удачи! – shellter

ответ

2

Я думаю, что нет никакого способа включения линии буферизации в BusyBox-х grep, но вы можете сделать что-то вроде этого:

$ adb shell timeout -t 10 getevent -t | \ 
    grep --line-buffered -v -E "add device|name:" | \ 
    while read line; do echo "READ: $line"; done 
+0

Это работает даже без '-line-buffered', используя adb (и Ubuntu), но эта же проблема появляется, как только я пытаюсь использовать ее в оболочке без '--line-buffered' (она не поддерживается, как вы сказали). – GermainZ

+0

Если вы пытаетесь сохранить список событий для последующего воспроизведения, использование главного компьютера, вероятно, является лучшим решением. –

+0

Вся идея состоит в том, чтобы использовать его на самом устройстве (например, для непосредственного использования с другими приложениями, например: LMT Launcher, Tasker и т. Д.) И поделиться им с аудиторией, которая может не работать с дистрибутивом Linux (или готова используйте Cygwin). – GermainZ

2

Здесь был в основном это материал, который я перевел из кода перед тем, как искажаются ошибка обходные пути. Заменив одну команду, которую я не имею с cat в ветке таймаута, он работает правильно с вашим примером ввода в Busybox sh, dash, mksh, bash и ksh93.

Поскольку так много основных вещей о оболочке и приложениях сломаны, это не удивительно, что это не работает. Я бы удостоверился, что Busybox обновлен и посмотреть, воспроизводятся ли арифметические и другие ошибки, которые вы продолжаете удалять, в других системах и сообщать об ошибках, если этот код не работает.

#!/bin/sh 

reader() { 
    t2=-1 
    grep -vE '^(add device|[[:space:]]+name:)' | 
    while IFS=' ' read -r t1 a b c d _; do 
     let "(t = (t1 = ${t1%%-*}) - t2) > 0 && t2 > -1" && echo "sleep $t" 
     printf 'sendevent %s' "${a%[[:digit:]]:}" 
     printf '%5d %5d %5d\n' "0x$b" "0x$c" "0x$d" 
     let t2=t1 
    done 
} 

let() { 
    IFS=, command eval test '$(($*))' -ne 0 
} 

countDown() { 
    echo 'Starting in...' 
    i=4 
    while let 'i-=1 > 0'; do 
     echo "$i" 
     sleep 1 
    done 
    printf '%s\n\n\n' 'Go!' 
    echo "$*" 
    "[email protected]" <&3 | reader 
} 

isDigit() { 
    while ! ${1+false}; do 
     case $1 in 
      *[^[:digit:]]*|'') return 1 
     esac 
     command shift 
    done 2>/dev/null 
} 

main() { 
    printf '%s >' 'Catch by [n]umber of events or [t]imeout?' 
    read type 

    case $type in 
     n) 
      printf '%s >' 'Events to catch?' 
      read arg 
      isDigit "$arg" || return 1 
      echo "Gonna catch $arg events!" 
      countDown getevent -t -c "$arg" 
      ;; 
     t) 
      printf '%s >' 'Timeout (in seconds)?' 
      read arg 
      isDigit "$arg" || return 1 
      echo "Gonna catch events for $arg seconds!" 
      countDown busybox timeout -t "$arg" cat - 
      ;; 
     *) 
      return 1 
    esac 
} 

main "[email protected]" 4<&0 <<\EOF 3<&0 <&4 4<&- 
add device 1: /dev/input/event8 
    name:  "bcm_headset" 
add device 2: /dev/input/event7 
    name:  "max8986_ponkey" 
add device 3: /dev/input/event6 
    name:  "sec_touchscreen" 
add device 4: /dev/input/event5 
    name:  "sec_keypad" 
add device 5: /dev/input/event4 
    name:  "orientation" 
add device 6: /dev/input/event3 
    name:  "accelerometer" 
add device 7: /dev/input/event0 
    name:  "proximity_sensor" 
add device 8: /dev/input/event2 
    name:  "geomagnetic_raw" 
add device 9: /dev/input/event1 
    name:  "geomagnetic" 
45534-48646 /dev/input/event6: 0001 008b 00000001 
45534-48646 /dev/input/event6: 0000 0000 00000000 
45534-48646 /dev/input/event6: 0001 008b 00000000 
45534-48646 /dev/input/event6: 0000 0000 00000000 
EOF 

# vim: set fenc=utf-8 ff=unix ft=sh : 

Выход:

$ bb --help 
BusyBox v1.21.0 (2013-02-20 20:39:21 CST) multi-call binary. 

Usage: bb [-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]]/FILE [ARGS]] 

Unix shell interpreter 
$ bb answers/countdown 
Catch by [n]umber of events or [t]imeout? >t 
Timeout (in seconds)? >5 
Gonna catch events for 5 seconds! 
Starting in... 
3 
2 
1 
Go! 


busybox timeout -t 5 cat - 
sendevent /dev/input/event6: 1 139  1 
sendevent /dev/input/event6: 0  0  0 
sendevent /dev/input/event6: 1 139  0 
sendevent /dev/input/event6: 0  0  0 
+0

Запросы задают ошибку: 'eval: arith: синтаксическая ошибка:" t2 = t1 " eval: arith: синтаксическая ошибка:" (t = (t1 = 45534) -t2)> 0 && t2> -1 "' Это означает, что преобразование действительно работает с 'cat', но эта же проблема воспроизводится (не выводится вообще - даже ошибки), когда я заменяю' cat' на 'getevent' или' getevent -t'. – GermainZ

0

была такая же проблема, и вспомнил трюк, который я впервые использовал в MS-DOS 3.30, а затем в Cygwin (не для тайм-аута, но тем больше команда является волшебная пуля для многих перенаправляют задач):

timeout -t 8 getevent | more > getevent.txt 

хорошо работает в оболочке Total Commander в с су (не ш)

Добро пожаловать :-)