脚本中的sshpass和svn commit:手动运行脚本时有效,使用Cron运行时失败

时间:2018-09-17 19:45:38

标签: bash github svn cron

我编写了一个Bash脚本,用于自动更新存储在SourceForge和GitHub上的某些文件。在文件结尾附近,我有两个命令分别将更新后的文件Rsync同步到SourceForge和Svn,将它们提交到GitHub(在有人问之前,我有使用Svn而不是Git的理由)。

我的问题是,尽管脚本执行了我手动运行时需要做的事情,但是将更改提交到GitHub的代码行失败,并出现身份验证错误。

我已经对该脚本进行了编程,以将Stderr的内容输出到日志文件中。这是我手动运行脚本后该文件的内容,并且可以正常工作:

auto_update_svn.bash:
17 Sep 2018 18:42 UTC
SSHPASS searching for password prompt using match "assword"
SSHPASS read: Authentication realm: <https://github.com:443> GitHub
SSHPASS read:

SSHPASS read: Password for 'XJDHDR':
SSHPASS detected prompt. Sending password.
SSHPASS read: *
<"SSHPASS read: *" repeated another 25 times
SSHPASS read:

SSHPASS read:

这是我通过Crontab运行脚本后日志显示的内容,但失败了:

auto_update_svn.bash:
16 Sep 2018 14:00 UTC
svn: E215004: Authentication failed and interactive prompting is disabled; see the --force-interactive option
svn: E215004: Commit failed (details follow):
svn: E215004: No more credentials or we tried too many times.
Authentication failed
svn: E200042: Additional errors:
svn: E120191: Error running context: The requested authentication type(s) are not supported

据我所知,当我使用Cron运行sshpass时,它没有运行,因此Svn没有收到密码。奇怪的是,由于前面几行,我将sshpass与Rsync一起使用将文件发送到SouceForge,并且在脚本通过Cron运行时有效。我经常看到的一种解决方案与Cron中的Path环境变量有关。我已在脚本顶部附近的这一行修复了此问题,但这对我的情况没有帮助:PATH=$PATH:$(grep 'PATH=' /etc/environment | sed 's/^.*=// ; s/\"//g')

这是我的Crontab中的内容:

0 14 *   *   *        /bin/bash /home/svn/xjdhdr-random-code/Bash/auto_update_svn.bash

这是我脚本的内容:

#!/bin/bash

PATH=$PATH:$(sed -n '/PATH=/s/^.*=// ; s/\"//gp' '/etc/environment')

sDateTime=$(date -u +"%d %b %Y %H:%M")
{
        # Commit changes
        #   SourceForge
        sshpass -f "$HOME/sourceforge_password.txt" rsync -qcruz -e ssh --exclude=.svn '/home/svn/xjdhdr-random-code/' \
                'xjdhdr@frs.sourceforge.net:/home/frs/project/xjdhdr-random-code/'

        #   GitHub
        svn status '/home/svn/xjdhdr-random-code/' | grep ^\? | cut -c2- | while IFS='' read -r sFile
        do
                svn add "$sFile"
        done
        sshpass -v -f "$HOME/github_password.txt" svn commit --username=XJDHDR --no-auth-cache \
                -m 'Automatic update of Adblock, Bash + blocklist files' '/home/svn/xjdhdr-random-code'
} 2> '/tmp/stderr-contents-auto_update_svn.txt'

if [ -f '/tmp/stderr-contents-auto_update_svn.txt' ]
then
        errors+=$(cat '/tmp/stderr-contents-auto_update_svn.txt')
        rm -f '/tmp/stderr-contents-auto_update_svn.txt'
fi


if [ -n "$errors" ]
then
        printf 'auto_update_svn.bash:\n%s UTC\n'"$errors"'\n\n' "$sDateTime" >> '/home/error_reports_to_email.txt'
fi

1 个答案:

答案 0 :(得分:0)

我设法找到问题的原因和解决方案。

首先,原因。 SSHPass要求运行该程序的程序必须提示输入密码,然后将其提供给提示程序。反之,Svn commit会提示您输入密码,如果没有通过命令行开关提供并且该密码正在交互环境中运行。这就是为什么我观察我观察到的东西手动运行脚本时,svn在交互式环境中运行。相反,当svn通过Cron运行时,它会检测到环境不是不是交互式的。因此,它不会提示您输入密码,并且SSHPass无法执行任何操作。

在这种情况下,解决方案是将开关--force-interactive添加到svn的命令中。因此,脚本中的相关行现在显示为:

sshpass -v -f "$HOME/github_password.txt" svn commit --username=XJDHDR --no-auth-cache --force-interactive \
        -m 'Automatic update of Adblock, Bash + blocklist files' '/home/svn/xjdhdr-random-code'

另一种可能的解决方案是使用有问题的密码将--password开关添加到svn命令中,并避免完全使用SSHPass。就我而言,这是行不通的,因为这需要将纯文本密码添加到脚本中。这给我带来了两个问题。首先,运行该脚本的服务器上的每个用户帐户都可以访问该脚本,而SSHPass使用的密码文件只能由执行该脚本的用户帐户读取。其次,此脚本是上传到我的SourceForge和GitHub存储库中的文件之一。