【问题标题】:How can I automate a bash script that is 'read'-ing from /dev/tty?如何自动化从 /dev/tty “读取”的 bash 脚本?
【发布时间】:2022-01-26 02:38:28
【问题描述】:

我有一个必须定期运行的脚本(我无法修改),它具有以下结构:

read -r response < /dev/tty
if [ "$response" = 'y' ]; then
...

我想包装这个脚本,这样我总是向它发送一个“y”字符。我尝试使用标准技巧运行脚本以发送是:

echo y | '/bin/bash /path/to/script'

yes | ./myscript

printf "y\n" | ./myscript

/bin/bash /path/to/script < /path/to/y-file

这些都不起作用。我也试过了。

目前尚不清楚 Mac OS X 的内置期望是否正常工作;启用期望诊断信息后,期望正确检测到提示并做出响应,但脚本随后终止。

#!/bin/bash
set timeout -1
SCRIPT="~/myscript"

expect -d <<EOF
spawn $SCRIPT
expect "prompt string"
send "y\r"
EOF

另外,澄清一下,这是在 Mac OS X Monterey 上。

如果有任何帮助,我将不胜感激。同样,我无法修改原始脚本。

【问题讨论】:

  • 大家可以随时关注expect
  • 如果你只想连续发送一个字符序列,你也可以使用yes(默认发送字符y,但你也可以指定另一个消息)。你可以这样称呼它:yes | script.sh
  • 这些建议仅适用于读取标准输入的内容,根据定义,此处并非如此。
  • stackoverflow.com/questions/32910661/… 和链接的问题似乎很有帮助,但并不是一个有效的解决方案。我尝试了socat 之一,但我无法成功,但可能我不明白我在做什么。可能expect 至少可以解决这个问题。

标签: bash input script


【解决方案1】:

您可以使用socat 为子进程伪造一个新的伪终端。

tty.sh 成为以下脚本:

#! /bin/bash

read -r response < /dev/tty
if [ "$response" = 'y' ]; then
  echo yes
else
  echo no
fi

那么就可以通过这种方式将stdin连接到子进程的新pty:

echo y | socat stdio exec:./tty.sh,pty,setsid,echo=0

【讨论】:

  • 这看起来很有希望,但有理由认为 MacOS 默认提供 socat 吗?如果不是,那么第 0 步将是“安装 socat”。
  • 感谢 ceving,这绝对是正确的方法,并且比其他方法效果更好。我认为我试图自动化的脚本正在产生更多的子 shell;我需要弄清楚。 BTW socat 可通过“brew install socat”在 Homebrew 上用于 macOS。
【解决方案2】:

您可以尝试使用 autoexpect 为您生成包装器(自动脚本)脚本:

autoexpect -f autoscript ./myscript.sh

【讨论】:

  • 如果它完全可行,expect 将是一种矫枉过正的方式。 OP 描述的所有已经尝试过的事情也会奏效。这里的问题是被包装的脚本直接从终端读取,而不是从脚本的标准输入读取。 Expect 不会将自己插入到脚本与其关联的终端之间。
猜你喜欢
  • 1970-01-01
  • 2018-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-30
  • 2018-01-25
相关资源
最近更新 更多