在命令行中自动输入输入


141

我正在运行一个脚本,要求在每次操作中输入“ y”,我正在寻找一种解决方案,例如$ ./script < echo 'yyyyyyyyyyyyyy'一次性传递所有输入。


有时,-f选项对于某些命令会很好地起作用。
iammilind

Answers:


257

有专门针对这种情况创建的命令: yes

$ yes | ./script

这是将的输出连接yes到的输入./script。因此,当./script要求用户输入时,它将获取的输出yes。的输出yes是无休止的y后跟换行符的流。基本上就像用户输入y的每个问题一样./script

如果您要说不(n)而不是(y),可以这样进行:

$ yes n | ./script

请注意,某些工具可以选择始终yes作为答案。例如,请参见此处:在“ apt-get upgrade”中跳过是/否提示


其他输入方法:

如果您确切知道y您的脚本期望多少,则可以执行以下操作:

$ printf 'y\ny\ny\n' | ./script

换行符(\n)是Enter键。

使用printf代替yes您可以对输入进行更细粒度的控制:

$ printf 'yes\nno\nmaybe\n' | ./script

请注意,在极少数情况下,该命令不需要用户在字符后按Enter。在这种情况下,请省略换行符:

$ printf 'yyy' | ./script

为了完整起见,您还可以使用here文档

$ ./script << EOF
y
y
y
EOF

或者,如果您的外壳支持它,则为here字符串

$ ./script <<< "y
y
y
"

或者,您可以创建一个文件,每行一个输入:

$ ./script < inputfile

如果命令足够复杂,并且以上方法不再足够,则可以使用Expect

这是一个超级简单的Expect脚本的示例:

spawn ./script
expect "are you sure?"
send "yes\r"
expect "are you really sure?"
send "YES!\r"
expect eof

技术nitpick:

您在问题中给出的假设命令调用不起作用:

$ ./script < echo 'yyyyyyyyyyyyyy'
bash: echo: No such file or directory

这是因为Shell语法允许在命令行中的任何位置进行重定向操作符。就外壳而言,您的假设命令行与此行相同:

$ ./script 'yyyyyyyyyyyyyy' < echo
bash: echo: No such file or directory

这意味着./script将使用参数调用,'yyyyyyyyyyyyyy'并且stdin将从名为的文件中获取输入echo。由于文件不存在,bash抱怨。


1
我得到一个cannot enable tty mode on non tty input。您知道解决方法吗?
bmpasini 2016年

当我尝试printf使用run需要自动执行安装过程的文件进行欺骗时,所有发生的事情是我收到一条错误消息Warning: Tried to connect to session manager, None of the authentication protocols specified are supported,并且该脚本在新的终端中打开,并要求我像往常一样手动输入输入。顺便说一下,这在Debian上正在发生。有什么建议么?
DavidB

需要更多细节。太大而无法评论。请询问所有细节的新问题。您可以在此处放置一个链接。
lesmana

在centos上“无用的破坏”没有任何作用
Drew

邪恶容易!适用于Google Cloud Beta SQL数据导入!非常感激!
G_Style

11

使用命令yes

yes | script

手册页摘录:

NAME
       yes - output a string repeatedly until killed

SYNOPSIS
       yes [STRING]...
       yes OPTION

DESCRIPTION
       Repeatedly output a line with all specified STRING(s), or 'y'.

9

某些事物(apt-get例如)接受特殊标志以在静默模式下运行(并接受默认值)。在apt-get这种情况下,您只需向其传递一个-y标志即可。不过,这完全取决于您的脚本。

如果您需要更复杂的东西,可以将脚本包装在Expect脚本中。Expect允许您读取输出并发送输入,因此您可以执行其他脚本不允许的非常复杂的事情。这是其Wikipedia页面中的示例之一

# Assume $remote_server, $my_user_id, $my_password, and $my_command were read in earlier
# in the script.
# Open a telnet session to a remote server, and wait for a username prompt.
spawn telnet $remote_server
expect "username:"
# Send the username, and then wait for a password prompt.
send "$my_user_id\r"
expect "password:"
# Send the password, and then wait for a shell prompt.
send "$my_password\r"
expect "%"
# Send the prebuilt command, and then wait for another shell prompt.
send "$my_command\r"
expect "%"
# Capture the results of the command into a variable. This can be displayed, or written to disk.
set results $expect_out(buffer)
# Exit the telnet session, and wait for a special end-of-file character.
send "exit\r"
expect eof

不能与.shshell脚本一起使用,对吧?还是有办法?
Shayan

7

在shell脚本中,您还可以使用以下生成,期望和发送技巧

spawn script.sh
expect "Are you sure you want to continue connecting (yes/no)?"
send "yes"

但是,在上述场景中,您将必须提供执行脚本时期望获得的短语,以获取更多示例,请转到以下链接

在Bash内期待


2

好的,这可能不是一个很好的解决方案,但是如果您将选项写在一个单独的文件中,然后将其作为脚本的输入传递,它也将正常工作。因此,如果您创建一个包含所有选项的新文件(将该文件称为“ options.in”),则可以轻松地使用运行脚本./script.sh < options.in并适当编辑/创建其他选项文件。


我应该如何写options.in文件?能给我举个例子吗?
Shayan

0

我正在用Dialog编写bash脚本,并且还需要自动执行此操作。我做到了,它就像一个魅力。

# -Wy force signaturewipe (if exists)
echo "y" | sudo lvcreate -W y -n $lvName -L "$lvSize"G /dev/"$svg" >> $nfsUtilLog

-1

您可以使用cat,从文本文件中通过提供用户输入的脚本,通过以下方式通过管道将其输入到脚本中bash

cat input.txt | bash your_script.sh

只需将所需的用户输入内容输入到input.txt文件中,即可获取所需的答案-y,n,数字,字符串等。



@muru对我来说,您提到的解决方案不起作用,所以我必须发明自己的解决方案。
WebComer

不太可能。你们两个描述的是同一件事。
大师

@muru从文件中提供答案的类似想法(可以通过几种方法完成)不是同一回事,而且它以完全不同的方式实现。您应该能够看到它。如果您指出的解决方案对我有用,那么我今天不会花时间重新发明轮子。您可以使用任何适合您的工作。
WebComer

@muru我相信两者之间是有区别的,其中的一些答案描述在此处askubuntu.com/questions/172982/…。例如,对我来说,将输出重定向到文件的代码似乎是从左到右的自然流,因此更加清晰。毕竟,对像您这样行之有效的解决方案的否决并不会刺激人们在这里分享他们的解决方案。我相信这足以消除不满。
WebComer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.