Trocando dados de entrada entre scripts de shell

2

Eu tenho um script de shell simples para ser executado no shell adb do Android.

while true; do
    read var1
    echo $var1 > /data/local/tmp/debug.txt
    am force-stop $var1
done

Funciona bem se eu inserir um valor no console da instância original do shell. Mas se eu abrir outro shell adb e tentar passar dados para o primeiro processo:

echo "com.package.name" > /proc/XXXX/fd/0

onde XXXX é o pid do primeiro shell, vejo apenas que a string "com.package.name" chega no read do primeiro shell, mas nem o debug echo line, nem o am line é executado . Esse é o script que parece esperar por algo, talvez um caractere de nova linha, mas adicionar \n , -e argumento e outras coisas na segunda entrada de shell não ajudou.

Como faço para passar dados corretamente entre scripts de shell?

    
por Stan 09.12.2015 / 16:58

1 resposta

1

Você está sendo assaltado pelo conceito usual, que tudo em um sistema Linux é um arquivo . Para ilustrar isso, coloquei seus comandos em um arquivo chamado forever , depois encontrei o PID do processo e, em seguida,

$ file /proc/25546/fd/*
  /proc/25546/fd/0:   symbolic link to '/dev/pts/12' 
  /proc/25546/fd/1:   symbolic link to '/dev/pts/12' 
  /proc/25546/fd/2:   symbolic link to '/dev/pts/12' 
  /proc/25546/fd/255: symbolic link to '/home/me/tmp/forever'
 $ file /dev/pts/12
  /dev/pts/12: character special

Isso mostra que seus descritores de arquivos 1,2,3 são arquivos de caractere. Agora, é bem conhecido (veja por exemplo esta resposta no Unix e Linux ) que:

Character devices (also called character special files) behave like pipes, serial ports, etc: writing or reading to them is an immediate action. But what the driver does with the data is its own business. Writing a byte to a character device might cause it to be displayed on screen, output on a serial port, converted into a sound, ... Reading a byte from a device might cause the serial port to wait for input, might return a random byte (/dev/urandom), ...

Então, você precisa de outra maneira de realizar o IPC (= Inter Process Communication). No Unix e no Linux , existem named pipes para isso. Modifique seu script da seguinte maneira:

#!/bin/bash

MYPIPE=/tmp/my_pipe
if [[ ! -p $MYPIPE ]]; then
     mkfifo $MYPIPE
fi

while true
do
     if read line <$pipe; then
         if [[ "$line" == 'quit' ]]; then
            break
         fi
         echo $line >> /tmp/debug.txt
     fi
done

echo "I quit"

Inicie o script; de outro tipo de terminal

 $ cat > /tmp/my_pipe
   My name is 
   George Washington 
    ....

De um terceiro terminal, usando tail -f /tmp/debug.txt , você verá o que acabou de digitar no segundo terminal, reaparecer de /tmp/debug.txt .

No Android , a situação é um pouco mais complexa, mas você encontrará aqui e aqui duas maneiras distintas em torno do problema de criar pipes nomeados em um dispositivo Android não enraizado (o primeiro é mais simples do que o segundo).

    
por 25.02.2016 / 18:26