无法在 cron 中获取远程 ssh 标准输出,但在我的终端中它可以工作

Posted

技术标签:

【中文标题】无法在 cron 中获取远程 ssh 标准输出,但在我的终端中它可以工作【英文标题】:Can't get remote ssh stdout output in cron, but in my terminal it works 【发布时间】:2019-02-07 22:37:56 【问题描述】:

上周我遇到了一个让我发疯的问题。我编写了一个 BASH 脚本,它与 acamai 建立远程 ssh 连接,然后执行一个简单的“ls”。我想将 'ls' sdtout 输出重定向到给定文件。

虽然脚本本身在手动运行时就像一个魅力,但在它通过 cron 运行时却没有。 cronjob 以 root 身份运行,每个命令都按预期工作,除了 ssh 命令。我的系统是 Gentoo Linux,而 cron 是旧的黄金 vixie-cron。

为了减少 200 LOC,我将基础知识放在这里(作为单个脚本)足以证明问题。

#!/bin/bash
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin'
#set -x
shopt -s lastpipe
exec 2>log.out
(ssh -i <path to key> -o HostKeyAlgorithms=+ssh-dss -o StrictHostKeyChecking=no <account@example.com> 'ls -r <path>') > '/root/listing.txt'

即使在ssh-vvv 调试模式下,我也可以看到,一切正常……只是我没有得到标准输出。 比我尝试在互联网上的另一个帖子中找到的其他方法:

#!/bin/bash
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin'
#set -x
shopt -s lastpipe
exec 2>log.out
(ssh -T -i <path to key> -o HostKeyAlgorithms=+ssh-dss -o StrictHostKeyChecking=no <account@example.com> 'ls -r <path>' </dev/zero) > '/root/listing.txt'

这里的缺点是,我启动了一个无法关闭的 ssh 会话,我猜这是由于 /dev/zero 造成的。 另一种方法是将 ssh 命令的子外壳 TEE 管道...这工作了很短的时间(为什么现在还不行?!)

现在我一无所知,需要帮助。 Cron 有它的 PATH,使用 BASH 等。很好奇我的老板用 java 成功地做到了这一点(他讨厌 BASH ......)。

非常欢迎任何解释和有用的提示。

【问题讨论】:

“我没有标准输出”是什么意思? 您是否尝试将-tt 添加到您的ssh 命令以强制分配一个伪终端? 另外,你是说 cron 通过 ssh 成功连接,问题是你没有得到标准输出?还是说ssh连接本身失败? 这个问题是只有在调用ls时才会出现,还是在将ls替换为date等其他命令时也会出现?您确定 cron 运行的任何用户都具有对 /root/listing.txt 的写权限吗?如果您将输出写入您知道每个人都可以访问的其他文件怎么办? 在您的 sn-p 中,不需要 ssh 周围的子外壳括号。你确定代码是在 bash 中运行的,而不是在它们不起作用的 /bin/sh 中吗? 【参考方案1】:

我有同样的问题,我为 CRON 编写脚本,它从远程 SSH 主机获取输出。 如果我手动运行脚本 - 它应该正常工作。但是当 CRON 运行它时 - 我只得到远程输出的一部分。

我不明白为什么会这样。

#!/bin/sh
pass=123
filelist=$(sshpass -p "$pass" ssh -q -tt -o StrictHostKeyChecking=no user@"10.10.10.10" "list")

filestring=$(echo "$filelist" | grep -Po "(\S+\s\S+\s+\d+\s\d2:\d2:\d2\s\d4)\slist0\.lst")
filedate=$filestring% list0.lst
echo $filedate
filestamp=$(date -d "$filedate" +"%s")
echo $filestamp

当我通过 CRON 在文件中获得回声时 - 有从 0:00:00 开始的日期 - 日期字段 (echo $filedate) 为空。但是当我手动运行时 - 我会得到正常的日期......

真的很困扰。

帮助?

我找到了解决方案 - 在 ssh 命令中添加“-tt”,所有输入都转到变量。

filelist=$(sshpass -p "$pass" ssh -q -tt -o StrictHostKeyChecking=no user@"10.10.10.10" "list")

【讨论】:

这并不能真正回答问题。如果您有其他问题,可以点击 进行提问。一旦你有足够的reputation,你也可以add a bounty 来引起对这个问题的更多关注。 - From Review 我发现了一些可以帮助主题启动器的思想... IDK 但我有类似的问题并想关注这个问题,因为作者不回答 cmets。

以上是关于无法在 cron 中获取远程 ssh 标准输出,但在我的终端中它可以工作的主要内容,如果未能解决你的问题,请参考以下文章

100 模拟ssh远程执行命令

cron 命令在共享主机中无法与 DirectAdmin 一起使用

无法在 VSCode 中 ssh 到远程机器

从 cron 运行时远程端口转发断开连接

如何从 paramiko 的标准输出中删除坏字符 [重复]

Perl 5.8 从 SSH 命令获取标准输出