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
行も実行されません。つまり、スクリプトは何か、おそらく改行文字を待っているようですが、 2 番目のシェル入力に 、引数\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
....
3 番目のターミナルから を使用するとtail -f /tmp/debug.txt
、2 番目のターミナルに入力した内容が から再表示されます/tmp/debug.txt
。
Androidの場合状況はもう少し複雑ですが、ここそしてここルート化されていない Android デバイスで名前付きパイプを作成する問題を回避する 2 つの異なる方法 (最初の方法は 2 番目の方法よりも簡単です)。