我正在尝试运行一个 shell 脚本,其中我将调用另一个脚本,第二个脚本等待提供一些命令。我已经使用 echo 来传递命令,但它不起作用。第二个脚本继续等待输入。
脚本1:
#!/bin/sh
set -x
sh script2.sh
echo ".open Simulation\n"
set +x
但这不会产生任何结果。它继续等待。
输出:
./script1.sh
+ sh script2
<Nothing appears here>
答案1
默认情况下,Linux 系统上的每个进程都有一个输入(stdin)和两个输出(stdout、stderr)。终端从键盘获取输入并将其发送到它们运行的 shell 的 stdin,并从进程中获取 stdout 和 stderr 并将其打印到屏幕。
当您在 shell 中(在终端中)运行命令时,它将自己的标准输入链接到进程的标准输入,因此您键入的任何键都会发送到该命令。它还将它们的 stdout 和 stderr 链接到它自己的(然后终端将其打印到屏幕上)。当您在脚本中运行命令时,也会发生同样的事情,stdin、stdout 和 stderr 链接到父进程的命令,这些最终传播到终端。
此外,脚本中的命令默认是阻塞的。只有当他们正在运行的命令完成后,他们才会执行下一个命令。
鉴于这些,让我们看看您的脚本(简化为感兴趣的两行):
sh script2.sh
echo ".open Simulation\n"
它的作用是运行 sh (运行 script2.sh)并将其标准输入附加到脚本的标准输入并阻止等待其结束。在第一个进程结束之前,第二行不会运行。
现在,您在 shell 中输入的任何内容.open Simulation\n
都会发送到 sh,后者会将其发送到您的script2.sh
.一旦(如果有的话)script2.sh
完成,它将退出,并且您的主脚本将回显.open Simulation\n
到 shell 并退出。
现在我们知道发生了什么事。我们该如何解决它?那么您可以覆盖 stdin、stdout 和 stderr 的默认附加到您想要的任何位置,包括文件或其他进程。为此,shell 必须拥有强大的实用程序、输入/输出重定向和命令管道。
I/O 重定向允许您将输入/输出重定向到您想要的任何文件解密,例如:
echo "contents of a file" > somefile.txt
这将通过将 echo 命令的 stdout 重定向到 来contents of a file
写入。输入重定向的工作方式相同:somefile.txt
somefile.txt
cat < somefile.txt
将通过重定向 cats stdin 来读取文件的内容到屏幕上somefile.txt
(请注意,这是一个人为的示例,大多数人只会cat somefile.txt
导致 cat 本身读取 somefile.txt 而不是让 shell 执行此操作。)
接下来是命令管道,它们允许您将一个程序的标准输出连接到另一个程序的标准输入。这听起来像您想要的,将 echo 的输出发送到脚本的 stdin 中:
echo ".open Simulation" | sh script2.sh
现在,这对于简单输入来说效果很好,但是如果您有超过几行,则有一种更简单的方法;此处文档。例如,要将多行管道传输到脚本中,您可以
sh script2.sh <<EOD
.open Simulation
.do something
.end Simulation
EOD
这会将三行(不包括 EOD)发送到您的脚本,准备好您的脚本进行处理。如果您需要做任何更高级的事情,您也可以使用子命令重定向,这将允许您将子 shell 的输出重定向到您的程序中,这里每行之间有一个 sleep 1:
sh script2.sh <(
echo ".open Simulation"
sleep 1
echo ".do something"
sleep 1
echo ".end Simulation"
)
在此示例中,您的脚本将.open Simulation
立即看到,然后在一秒钟后它将在 stdin 关闭之前.do something
再过一秒。.end Simulation
答案2
尝试
echo ".open Simulation" | sh script2.sh
因为在您的脚本中,您刚刚启动 script2.sh 并且它正在等待输入。使用管道将 echo 的输出发送到 script2.sh 的标准输入
抱歉,您不需要在 echo 中插入 '\n',因为它默认打印换行符。 (谢谢三哥)