在 Shell 脚本之间交换输入数据

在 Shell 脚本之间交换输入数据

我有一个简单的 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

在 Android 上,情况稍微复杂一些,但你会发现这里这里解决非 rooted Android 设备上创建命名管道的问题的两种不同方法(第一种方法比第二种更简单)。

相关内容