来自cronjob的“stdin:不是一个tty”

时间:2014-10-02 09:11:34

标签: linux bash cron crontab

每次执行特定的cronjob时,我都会收到以下邮件。当我直接调用它甚至是来自cron时,被调用的脚本运行正常。因此,我得到的消息不是实际错误,因为脚本完全按照它应该做的那样。

这是cron.d条目:

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

和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 $1}')
iv=$(echo $encrypted | awk -F '#' '{print $2}' |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

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

3 个答案:

答案 0 :(得分:10)

你实际上有两个问题。

  1. 为何打印stdin: is not a tty
  2. 此警告消息由bash -l打印。 -l--login)选项要求bash启动登录shell,例如通常在您输入密码时启动的那个。在这种情况下,bash期望其stdin成为真正的终端(例如,isatty(0)调用应该返回1),如果它由cron运行则不正确 - 因此这个警告。

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

    $ ssh user@example.com 'bash -l -c "echo test"'
    Password:
    stdin: is not a tty
    test
    

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

    1. 为什么没有-l无效?
    2. 正如@Cyrus在评论中正确陈述的那样,bash在启动时加载的文件列表取决于会话的类型。例如。对于登录shell,它将加载/etc/profile~/.bash_profile~/.bash_login~/.profile(请参阅手册bash(1)中的INVOCATION),而对于非登录shell,它将加载仅加载~/.bashrc。您似乎只在为登录shell加载的一个文件中定义了http_proxy变量,而在~/.bashrc中没有。您已将其移至~/.wgetrc并且它是正确的,但您也可以在~/.bashrc中对其进行定义,这样就可以了。

答案 1 :(得分:1)

在.profile中,更改

mesg n

if `tty -s`; then
  mesg n
fi

答案 2 :(得分:0)

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

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

如果遇到此问题,请检查是否按预期设置了所有环境变量。感谢Cyrus让我走向了正确的方向。