bash 来自 cronjob 的“标准输入:不是 tty”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26157703/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 11:27:29  来源:igfitidea点击:

"stdin: is not a tty" from cronjob

linuxbashcroncrontab

提问by Kai

I'm getting the following mail every time I execute a specific cronjob. The called script runs fine when I'm calling it directly and even from cron. So the message I get is not an actual error, since the script does exactly what it is supposed to do.

每次执行特定的 cronjob 时,我都会收到以下邮件。当我直接甚至从 cron 调用它时,被调用的脚本运行良好。所以我得到的消息不是一个实际的错误,因为脚本完全按照它应该做的。

Here is the cron.d entry:

这是 cron.d 条目:

* *     * * *     root   /bin/bash -l -c "/opt/get.sh > /tmp/file"

and the get.sh script itself:

和 get.sh 脚本本身:

#!/bin/sh

#group and url
groups="foo"

url="https://somehost.test/get.php?groups=${groups}"

# encryption
pass='bar'
method='aes-256-xts'
pass=$(echo -n $pass | xxd -ps | sed 's/[[:xdigit:]]\{2\}/&/g')

encrypted=$(wget -qO- ${url})
decoded=$(echo -n $encrypted | awk -F '#' '{print }')
iv=$(echo $encrypted | awk -F '#' '{print }' |base64 --decode | xxd -ps | sed 's/[[:xdigit:]]\{2\}/&/g')

# base64 decode input and save to file
output=$(echo -n $decoded | base64 --decode | openssl enc -${method} -d -nosalt -nopad -K ${pass} -iv ${iv})

if [ ! -z "${output}" ]; then
        echo "${output}"
else
        echo "Error while getting information"
fi

When I'm not using the bash -lsyntax the script hangs during the wget process. So my guess would be that it has something to do with wget and putting the output to stdout. But I have no idea how to fix it.

当我不使用bash -l语法时,脚本会在 wget 过程中挂起。所以我的猜测是它与 wget 和将输出放到 stdout 有关。但我不知道如何解决它。

回答by afenster

You actually have two questions here.

你实际上有两个问题。

  1. Why it prints stdin: is not a tty?
  1. 为什么会打印stdin: is not a tty

This warning message is printed by bash -l. The -l(--login) options asks bashto start the login shell, e.g. the one which is usually started when you enter your password. In this case bashexpects its stdinto be a real terminal (e.g. the isatty(0)call should return 1), and it's not true if it is run by cron—hence this warning.

此警告消息由 打印bash -l。在-l--login)选项要求bash启动登录shell,例如在一个当你输入密码,这通常是开始。在这种情况下,bash期望它stdin是一个真正的终端(例如,isatty(0)调用应该返回 1),如果它是由运行的,则它不是真的 - 因此cron出现此警告。

Another easy way to reproduce this warning, and the very common one, is to run this command via ssh:

重现此警告的另一种简单方法,也是非常常见的方法,是通过ssh以下方式运行此命令:

$ ssh [email protected] 'bash -l -c "echo test"'
Password:
stdin: is not a tty
test

It happens because sshdoes not allocate a terminal when called with a command as a parameter (one should use -toption for sshto force the terminal allocation in this case).

发生这种情况是因为ssh在使用命令作为参数调用时不分配终端(在这种情况下应该使用-t选项ssh来强制终端分配)。

  1. Why it did not work without -l?
  1. 为什么它没有工作-l

As correctly stated by @Cyrus in the comments, the list of files which bashloads on start depends on the type of the session. E.g. for login shells it will load /etc/profile, ~/.bash_profile, ~/.bash_login, and ~/.profile(see INVOCATION in manual bash(1)), while for non-login shells it will only load ~/.bashrc. It seems you defined your http_proxyvariable only in one of the files loaded for login shells, but not in ~/.bashrc. You moved it to ~/.wgetrcand it's correct, but you could also define it in ~/.bashrcand it would have worked.

正如@Cyrus 在评论中正确指出的那样,bash启动时加载的文件列表取决于会话的类型。例如,对于登录 shell,它将加载/etc/profile, ~/.bash_profile, ~/.bash_login, 和~/.profile(参见手册中的 INVOCATION bash(1)),而对于非登录 shell,它只会加载~/.bashrc. 似乎您http_proxy只在为登录 shell 加载的文件之一中定义了变量,但不在~/.bashrc. 你把它移到~/.wgetrc并且它是正确的,但你也可以定义它~/.bashrc并且它会起作用。

回答by user1130176

in your .profile, change

在您的 .profile 中,更改

mesg n

to

if `tty -s`; then
  mesg n
fi

回答by Kai

I ended up putting the proxy configuration in the wgetrc. There is now no need to execute the script on a login shell anymore.

我最终将代理配置放在 wgetrc 中。现在不再需要在登录 shell 上执行脚本了。

This is not a real answer to the actual problem, but it solved mine.

这不是对实际问题的真正答案,但它解决了我的问题。

If you run into this problem check if you are getting all the environment variables set as you expect. Thanks to Cyrus for putting me to the right direction.

如果遇到此问题,请检查是否按照预期设置了所有环境变量。感谢赛勒斯把我带到正确的方向。