2

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

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 ответ1

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 ситуация немного сложнее, но здесь и здесь вы найдете два разных способа решения проблемы создания именованных каналов на некорневом устройстве Android (первый проще, чем второй).

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .