Обмен входными данными между скриптами оболочки

Обмен входными данными между скриптами оболочки

У меня есть простой скрипт оболочки для запуска в Android adb shell.

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

Работает нормально, если я ввожу значение в консоль исходного экземпляра оболочки. Но если я открою другую оболочку adb и попытаюсь передать данные в первый процесс:

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

где XXXX - это pid первой оболочки, я вижу только, что строка "com.package.name" приходит в read, но ни echoстрока отладки, ни amстрока не выполняются. То есть скрипт, похоже, ждет чего-то, возможно, символа новой строки, но добавление \n, -eаргумента и прочего во входные данные второй оболочки не помогло.

Как правильно передавать данные между скриптами оболочки?

решение1

Вас подстерегает обычная концепция, чтовсе в системе Linux является файлом. Чтобы проиллюстрировать это, я поместил ваши команды в файл с именем forever, затем нашел PID процесса, затем

$ 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

Это показывает, что ваши файловые дескрипторы 1,2,3 являются символьными файлами. Теперь, это хорошо известно (см. напримерэтот ответ на Unix и Linux) что:

Символьные устройства (также называемые символьными специальными файлами) ведут себя как каналы, последовательные порты и т. д.: запись или чтение в них — немедленное действие. Но то, что драйвер делает с данными,свой собственный бизнесЗапись байта на символьное устройство может привести к его отображению на экране, выводу на последовательный порт, преобразованию в звук, ... Чтение байта с устройства может привести к тому, что последовательный порт будет ожидать ввода, может вернуть случайный байт (/dev/urandom), ...

Поэтому вам нужен другой способ реализации IPC (межпроцессного взаимодействия).В Unix и Linux, есть именованные каналыдля этого. Измените ваш скрипт следующим образом:

#!/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"

Запустите скрипт; с другого терминала введите

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

На третьем терминале с помощью tail -f /tmp/debug.txt, вы увидите то, что только что ввели во второй терминал, снова появившийся из /tmp/debug.txt.

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

Связанный контент