首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有可能使bash脚本与另一个命令行程序交互?

是否有可能使bash脚本与另一个命令行程序交互?
EN

Stack Overflow用户
提问于 2010-08-10 11:35:51
回答 6查看 25.6K关注 0票数 10

我在运行bash的Linux终端中使用交互式命令行程序。我有一个明确的命令序列,输入到shell程序。程序将其输出写入标准输出。其中一个命令是“保存”命令,它将上一个运行的命令的输出写入磁盘文件。

一个典型的循环是:

代码语言:javascript
复制
$prog
$$cmdx
$$<some output>
$$save <filename>
$$cmdy
$$<again, some output>
$$save <filename>
$$q
$<back to bash shell>
  • $是bash提示符
  • $$是程序的提示符
  • Q是prog的退出命令。
  • prog将前面命令的输出附加到文件名中。

如何使此过程自动化?我想写一个shell脚本,它可以启动这个程序,并循环这些步骤,一个接一个地给它输入命令,然后退出。我希望保存命令能正常工作。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2010-08-10 14:27:03

如果您的命令不关心您给它输入的速度,也不需要与它交互,那么您可以使用heredoc。

示例:

代码语言:javascript
复制
#!/bin/bash
prog <<EOD
cmdx
save filex
cmdy
save filey
q
EOD

如果您需要根据程序的输出进行分支,或者您的程序对命令的时间完全敏感,那么期望就是您想要的。

票数 19
EN

Stack Overflow用户

发布于 2010-08-10 11:45:40

我建议您使用期望。此工具旨在自动化交互式shell应用程序。

票数 12
EN

Stack Overflow用户

发布于 2014-08-28 06:19:06

哪里有需要,哪里就有办法!我认为这是一个很好的教训,看看进程管理和ipc是如何工作的。当然,最好的解决办法是期待。但真正的原因是管道可能很棘手,而且许多命令都是为了等待数据而设计的,这意味着由于难以预测的原因,流程将变成僵尸。但是学习如何和为什么会提醒我们在引擎盖下发生了什么。

当两个进程进行对话时,危险在于其中一个或两个进程都会试图读取永远不会到达的数据。交战规则必须非常清楚。像CRLF和字符编码之类的东西会让党丧命。幸运的是,像bash脚本及其子进程这样的两个密切合作伙伴相对来说很容易保持一致。最容易错过的事情是bash为它所做的每一件事启动一个子进程。如果你能让它和bash一起工作,你就完全知道你在做什么。

关键是我们想要与另一个过程对话。这里有一个服务器:

代码语言:javascript
复制
# a really bad SMTP server

# a hint at courtesy to the client
shopt -s nocasematch

echo "220 $HOSTNAME SMTP [$$]"

while true
do
    read
    [[ "$REPLY" =~ ^helo\ [^\ ] ]] && break
    [[ "$REPLY" =~ ^quit ]] && echo "Later" && exit
    echo 503 5.5.1 Nice guys say hello.
done

NAME=`echo "$REPLY" | sed -r -e 's/^helo //i'`
echo 250 Hello there, $NAME 

while read
do
    [[ "$REPLY" =~ ^mail\ from: ]] && { echo 250 2.1.0 Good guess...; continue; }
    [[ "$REPLY" =~ ^rcpt\ to: ]] && { echo 250 2.1.0 Keep trying...; continue; }
    [[ "$REPLY" =~ ^quit ]] && { echo Later, $NAME; exit; }
    echo 502 5.5.2 Please just QUIT
done

echo Pipe closed, exiting

现在,希望能带来魔力的剧本。

代码语言:javascript
复制
# Talk to a subprocess using named pipes

rm -fr A B      # don't use old pipes
mkfifo A B

# server will listen to A and send to B
./smtp.sh < A > B &

# If we write to A, the pipe will be closed.
# That doesn't happen when writing to a file handle.
exec 3>A

read < B
echo "$REPLY"

# send an email, so long as response codes look good
while read L
do
    echo "> $L"
    echo $L > A
    read < B
    echo $REPLY
    [[ "$REPLY" =~ ^2 ]] || break

done <<EOF
HELO me
MAIL FROM: me
RCPT TO: you
DATA
Subject: Nothing

Message
.
EOF

# This is tricky, and the reason sane people use Expect.  If we
# send QUIT and then wait on B (ie. cat B) we may have trouble.
# If the server exits, the "Later" response in the pipe might
# disappear, leaving the cat command (and us) waiting for data.
# So, let cat have our STDOUT and move on.
cat B &

# Now, we should wait for the cat process to get going before we
# send the QUIT command. If we don't, the server will exit, the
# pipe will empty and cat will miss its chance to show the
# server's final words.
echo -n > B     # also, 'sleep 1' will probably work.

echo "> quit"
echo "quit" > A

# close the file handle
exec 3>&-

rm A B

注意,我们并不是简单地将SMTP命令转储到服务器上。我们检查每个响应代码以确保一切正常。在这种情况下,事情就不会好了,剧本也会被保释。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3448468

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档