Sea*_*ian 5 scripting bash web-server documentation jenkins
我正在使用 Jenkins 构建 HTML 文档并将其部署到本地 Apache Web 服务器以供我们的开发人员使用。当我在终端中运行命令时,一切都安装正确(证明服务器设置正确)。但是,当从 Jenkins 内部运行相同的命令时,它们会被调用但没有任何变化。它不会删除html.zip
(第 18 行),不会将文件移动到 中/var/html/www/subdir
,并且不会报告curl
请求失败之外的任何错误。我对我做错了什么有点迷茫。
我应该注意,我将整个脚本称为sudo
. 我知道这是不安全的,但我想我会先尝试让脚本工作,然后再更改。为了确保user
在安装文档时不会遇到问题,我暂时允许它以 sudo 身份运行任何命令而无需密码。同样,我知道这是不安全的,但本着试图消除变量的精神,我添加了这个。
Jenkins 像这样调用这个脚本:
sudo ./documentation-publisher.sh
目前对脚本的权限限制最少,777。调用ls -l
脚本报告:
-rwxrwxrwx 1 devop developers 1144 Dec 3 10:29 documentation-publisher.sh
我尝试了这篇文章中关于在脚本中显式设置路径的建议,但没有发现任何差异。使用的每个命令的显式路径也不会改变行为。
#!/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
Run Code Online (Sandbox Code Playgroud)
我可能做错了什么?
看起来您想要ssh
进入 my.host.example.com,然后让脚本的其余部分在该主机上运行。如果是这种情况,您需要将脚本的其余部分作为命令的输入传递ssh
;就像现在一样,ssh
正在从脚本的标准输入获取输入,该输入可能为空,因此它打开一个远程 shell 会话,向其发送文件结尾,这将关闭会话ssh
并在本地执行脚本的其余部分。为了远程运行这些命令,您需要将它们作为ssh
命令的输入传递,如下所示:
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
Run Code Online (Sandbox Code Playgroud)
其次,该脚本没有错误检查。一般来说,最好查看脚本中的每个命令,并问问自己如果失败会发生什么。脚本的其余部分应该继续,还是会“脱离轨道”并做出一些愚蠢的事情?例如,如果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
}
Run Code Online (Sandbox Code Playgroud)
...或者使用 shell 的-e
选项使其在任何命令失败时退出脚本。此选项使您不必单独对每个命令进行错误检查,但不会提供信息丰富的错误消息,并且如果无关紧要的内容由于某种原因返回错误状态,则可能会因退出脚本而导致麻烦(请参阅 BashFAQ #105 )有关为什么-e
会导致意外行为的一些示例)。另外,如果您确实选择此选项,请确保set -e
在脚本的开头使用这两个选项(或-xe
在 shebang 行上使用),并添加set -e
为发送到远程计算机的第一个命令。
顺便说一句,cd
第 4 行的命令特别有可能失败,因为它使用相对路径。这意味着它尝试访问的目录cd
取决于脚本启动的工作目录。请注意,这不一定是脚本所在的目录,它是从启动脚本的进程继承的,因此几乎可以是任何目录。Jenkins 可能会使用与您不同的工作目录来启动脚本,从而导致它立即失败。好吧,实际上并不是失败,只是在错误的目录中运行所有剩余的命令(并且由于ssh
输入问题,在错误的主机上运行)。