我正在开发一个不需要与用户交互的脚本,如果我的脚本中的程序需要用户输入内容,脚本应该会失败并立即退出。
我已经关闭了我脚本顶部的STDIN
,这适用于某些命令,但有些人希望输入另一个文件描述符(通常是那些要求输入{{1}的密码}或git
)。
目前我的脚本是:
sudo
那么,我该如何避免这种情况呢?
注意:我不是在#!/bin/bash
# close STDIN
exec 0<&-
# test that $1 exists and it is a valid folder containing a git repository
# ...
cd "$1"
git fetch
# if git is not correctly configured, it asks for a password and
# my script waits for it :(
或git
或sudo
询问如何进行无密码配置,而是要阻止whatever
中的程序(或bash
)期望用户输入并在发生这种情况时立即失败。
答案 0 :(得分:3)
首先让我说我不认为这是解决问题的正确方法。完全没有。必须有一个更好的特定于应用程序的解决方案,你真的应该找到它。
主要问题是,如果不知道你想要“强行关闭”哪些程序,你就不会知道如何让它们“错误”。如果你做知道程序,CodeGnome的解决方案似乎没问题。
另请注意,并非所有程序都直接从STDIN读取输入。例如,Python的getpass模块直接向/dev/tty
打开一个额外的文件描述符,因此关闭或重定向STDIN无关紧要。这也是sudo
接受密码的方式,我相信这也是ncurses的工作方式。以这种方式阅读可以让你获得密码,而不会在屏幕上显示密码。
对于不直接从/dev/tty
读取的提示(例如bash的read
),只需从/dev/null
(例如./prompt.sh </dev/null
)重定向STDIN,就可能找到某个地方。或者,您可以执行您正在执行的操作并关闭STDIN, ,但程序在遇到已关闭的STDIN或仅包含EOF的重定向STDIN时的行为方式是您无法控制的。 < / strong>希望程序会根据您的意愿出错,但也许它会继续循环,期望有效的输入。谁知道?
此外,如果有的话,关闭或重定向都不会全局成为可行的方式。有些程序可能因为您希望关闭STDIN而退出,其他程序可能需要来自/dev/null
所以这样做的方法并不是一种通用的,全能型的解决方案,而是针对您放置在该位置的程序量身定制的解决方案。更好的是,不要使用尝试(运行程序),然后 catch (程序要求输入的情况)方法,只需调用程序方式 你知道 他们不会要求输入。
无论如何,所有这一切,可能有用的一种可能性就是关闭STDIN并对该过程进行后台处理。例如:
#!/bin/bash
exec 0<&-
./prompt.sh &
或者,将STDIN重定向到/ dev / null并将该过程作为后台。例如:
#!/bin/bash
./prompt.sh </dev/null &
然后,您需要检查程序的返回代码(使用$?
)以查看它们是否正确退出。 (希望您使用的未知程序列表遵循标准的返回值方案)
关闭/重定向STDIN将处理STDIN用于接受输入和后台处理的情况,该过程将处理/dev/tty
的情况(因为后台进程没有tty)。
如果程序提示您使用其他方法(直接向您的伪终端打开FD,弹出图形输入框,向您显示声音提示等等),您就可以自行使用。
答案 1 :(得分:2)
与其尝试关闭标准输入或标准错误,您可能最好只使用一个短期望脚本,如果它看到密码提示,则会挽救。例如:
#!/bin/bash
cd "$1"
expect -c '
log_user 0
spawn git fetch
expect -timeout 30 -re "ass(phrase|word)" { exit 1 }
'
# Do something based on the exit status of the expect script.
[[ $? -eq 1 ]] && { echo 'Password prompt detected!' >&2; exit 1; }
如果看到密码或密钥密码提示,则expect脚本将以退出状态1返回。然后bash脚本可以自由地执行,或采取其他操作。
希望有所帮助!
答案 2 :(得分:0)
大多数(全部?)* NIX都有tty
命令打印出shell tty
的名称,如果shell附加了tty则退出0
,否则退出{ {1}}错误。
1