use*_*496 1 shell shell-script
我正在尝试在其中运行一个 shell 脚本,我将调用另一个脚本,第二个脚本等待提供一些命令。我已经使用 echo 来传递命令,但它不起作用。第二个脚本继续等待输入。
脚本1:
#!/bin/sh
set -x
sh script2.sh
echo ".open Simulation\n"
set +x
Run Code Online (Sandbox Code Playgroud)
但这不会产生任何结果。它一直在等待。
输出:
./script1.sh
+ sh script2
<Nothing appears here>
Run Code Online (Sandbox Code Playgroud)
默认情况下,Linux 系统上的每个进程都有一个输入(stdin)和两个输出(stdout、stderr)。终端从键盘获取输入并将其发送到它们运行的 shell 的 stdin,然后从进程中获取 stdout 和 stderr 并将其打印到屏幕上。
当您在 shell 中(在终端中)运行命令时,它会将自己的 stdin 链接到进程的 stdin,因此您键入的任何键都会发送到该命令。它还将它们的 stdout 和 stderr 链接到自己的(然后终端打印到屏幕上)。当您在脚本中运行命令时,也会发生同样的事情,stdin、stdout 和 stderr 链接到父进程的命令,这些最终传播到终端。
此外,脚本中的命令默认是阻塞的。他们只会在他们正在运行的命令完成后执行下一个命令。
鉴于这些,让我们看看您的脚本(简化为感兴趣的两行):
sh script2.sh
echo ".open Simulation\n"
Run Code Online (Sandbox Code Playgroud)
它的作用是运行 sh(运行 script2.sh)并将其 stdin 附加到脚本的 stdin 并阻塞等待它结束。在第一个进程结束之前,第二行不会运行。
现在,例如,您在 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
Run Code Online (Sandbox Code Playgroud)
这将写入contents of a file到somefile.txt通过重定向echo命令的标准输出somefile.txt。输入重定向的工作方式相同:
cat < somefile.txt
Run Code Online (Sandbox Code Playgroud)
将通过重定向cats stdin 来读取文件的内容将打印到屏幕上somefile.txt(请注意,这是一个人为的例子,大多数人只会cat somefile.txt导致 cat 读取 somefile.txt 本身而不是让 shell 来执行它。)
接下来是命令管道,它们允许您将一个程序的 stdout 连接到另一个程序的 stdin。这听起来像您想要的,将 echo 的输出发送到脚本的 stdin 中:
echo ".open Simulation" | sh script2.sh
Run Code Online (Sandbox Code Playgroud)
现在这适用于简单的输入,但如果你有超过几行,有一个更简单的方法;继承人。例如,将多行管道传输到您的脚本中,您可以
sh script2.sh <<EOD
.open Simulation
.do something
.end Simulation
EOD
Run Code Online (Sandbox Code Playgroud)
这会将三行(不包括 EOD)发送到您的脚本,以便您的脚本进行处理。如果你需要做任何更高级的事情,你也可以使用子命令重定向,这将允许你将子shell的输出重定向到你的程序中,这里每行之间有一个 sleep 1 :
sh script2.sh <(
echo ".open Simulation"
sleep 1
echo ".do something"
sleep 1
echo ".end Simulation"
)
Run Code Online (Sandbox Code Playgroud)
在此示例中,您的脚本将立即看到.open Simulation,然后在一秒钟后它会在 stdin 关闭之前.do something再过一秒钟.end Simulation。