我有一個簡單的 shell 腳本可以在 Android adb shell 中運行。
while true; do
read var1
echo $var1 > /data/local/tmp/debug.txt
am force-stop $var1
done
如果我在原始 shell 實例的控制台中輸入一個值,它就可以正常運作。但是如果我打開另一個 adb shell 並嘗試將資料傳遞到第一個進程:
echo "com.package.name" > /proc/XXXX/fd/0
其中 XXXX 是第一個 shell 的 pid,我只看到字串「com.package.name」到達第一個 shell 中read
,但偵錯echo
行和am
行都沒有執行。那是腳本似乎在等待某些東西,也許是換行符,但是將\n
、-e
參數和其他內容添加到第二個 shell 輸入中並沒有幫助。
如何在 shell 腳本之間正確傳遞資料?
答案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
。
在安卓上,情況有點複雜,但你會發現這裡和這裡有兩種不同的方法可以解決在非 root Android 裝置上建立命名管道的問題(第一種方法比第二種方法更簡單)。