我应该注意到我将整个脚本称为sudo.我知道这是不安全的,但我想我会尝试让脚本先运行,然后再改变它.为确保用户不会遇到安装文档的问题,我暂时允许它在没有密码的情况下以sudo身份运行任何命令.我再次知道这是不安全的,但本着努力消除变量的精神,我补充说.
Jenkins这样调用这个脚本:
sudo ./documentation-publisher.sh
目前,脚本的权限限制最少,777.在脚本报告上调用ls -l:
-rwxrwxrwx 1 devop developers 1144 Dec 3 10:29 documentation-publisher.sh
我尝试了this post关于在脚本中明确设置路径的建议,但没有发现任何差异.每个使用的命令的显式路径也不会改变行为.
#!/bin/sh -x echo "Archiving generated HTML for transfer..." cd Example/docs/html/ zip -r html.zip ./ scp -i ~/.ssh/id_rsa html.zip user@my.host.example.com:/home/user ssh -i ~/.ssh/id_rsa user@my.host.example.com echo "Extracting generated HTML into www directory..." PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games unzip -o html.zip -d ./subdir rm -r /var/www/html/subdir mkdir /var/www/html/subdir cp -r ./subdir/* /var/www/html/subdir/ echo "Cleaning up after file transfer..." rm -rf ./subdir rm ./html.zip echo "Testing install..." curl -f my.host.example.com/subdir/index.html exit
我能做错什么?
解决方法
ssh -i ~/.ssh/id_rsa user@my.host.example.com <<EOF echo "Extracting generated HTML into www directory..." PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games [...] exit EOF
其次,脚本没有错误检查.一般来说,查看脚本中的每个命令是个好主意,并问自己如果失败会发生什么.如果脚本的其余部分继续,或者它会“脱轨”并做一些愚蠢的事情?例如,如果scp命令失败(无论出于何种原因),那么运行脚本的其余部分就没有任何意义(它可能具有破坏性,消除/ var / www / html / subdir然后替换它与……哎呀,没什么).您可以对每个单独命令的退出状态运行错误检查,例如:
scp -i ~/.ssh/id_rsa html.zip user@my.host.example.com:/home/user || { echo "Failed to scp the html files to my.host.example.com." >&2 exit 1 }
…或者使用shell的-e选项使其在任何命令失败时退出脚本.一些选项可以使您不必单独对每个命令进行错误检查,但不会提供信息性错误消息,并且如果由于某种原因返回错误状态,则退出脚本会导致出现问题(有关某些原因,请参阅BashFAQ #105)为什么-e会导致意外行为的例子.此外,如果您使用此选项,请确保在脚本开头使用set -e(或在shebang行上使用-xe),并将set -e添加为发送到远程计算机的第一个命令.
顺便说一下,第4行的cd命令特别容易失败,因为它使用相对路径.这意味着它尝试cd到的目录取决于脚本启动的工作目录.请注意,这不一定是脚本所在的目录,它继承自启动脚本的进程,因此几乎可以是任何内容. Jenkins可能正在使用与您不同的工作目录启动脚本,从而导致它失败.好吧,实际上并没有失败,只是在错误的目录中运行所有剩余的命令(并且由于ssh输入问题,在错误的主机上).