问题描述
Jenkins 2.7.4已安装在RedHat Server中,并且通过选择通过在主服务器上执行命令来启动代理"选项来配置Linux Slave.我们创建了一个Shell脚本,并且在Jenkins 2.7.4版中可以正常工作.
Jenkins 2.7.4 was installed in the RedHat Server and Linux Slaves is configured by Selecting "Launch agent via execution of command on master" option. We created a Shell script and it works fine in the Jenkins version 2.7.4.
现在,我们将Jenkins升级到2.121.1.现在,相同的脚本会引发错误
Now we upgraded the Jenkins to 2.121.1. Now the same script throws an error
如果我在Manage Jenkins-> Configure Security中禁用了SSHD端口,则可以启动我的奴隶.但是在我的脚本中,我将使用Jenkins-cli.jar触发一项作业,将二进制文件从主服务器复制到从属服务器.java -jar jenkins-cli.jar -s http://localhost:8080 --ssh -user username -i ~/.ssh/id_rsa build RTT/RTT-CI-Tools/RTT-CI-Tools-Distribute -s -p SLAVE_REGEX=slave name
我收到一条消息
If I disable the SSHD port in Manage Jenkins -> Configure Security, Then I can able to launch my slave. But In my script, I will trigger one job using Jenkins-cli.jar to copy the binaries from master to slaves.java -jar jenkins-cli.jar -s http://localhost:8080 --ssh -user username -i ~/.ssh/id_rsa build RTT/RTT-CI-Tools/RTT-CI-Tools-Distribute -s -p SLAVE_REGEX=slave name
I'm getting a message as
"WARNING: No header 'X-SSH-Endpoint' returned by Jenkins"
并且构建未触发.我也尝试过在jenkins-cli.jar命令中将-ssh替换为-http,
and build is not getting triggered. I have also tried by replacing -ssh to -http in jenkins-cli.jar command,
java -jar jenkins-cli.jar -s http://localhost:8080 -http -auth username:60b3450a883a2519592af84cdcd0d224 build $CI_JOB -s -p SLAVE_REGEX=$SLAVEHOST
它将触发作业.再次无法启动从机,
It triggers the job. Again unable to launch the slave machine,
如何解决此问题
推荐答案
未更改的标准输入,未更改的标准输出
我相信您脚本中的某些内容正在篡改stdin.
Unaltered stdin, unaltered stdout
I believe something in your script is tampering with stdin.
您的脚本应将完整的 stdin流传递给Jenkins代理进程.
Your script should pass the entire, unaltered stdin stream to the Jenkins agent process.
OP建立Jenkins会话的命令与我的不同,但是无论如何,您应该将启动脚本分为三个主要部分:
OP's command to establish a Jenkins session is different from mine, but regardless, you should split your launch script into 3 major parts:
设置:在此部分中请勿篡改stdin或stdout.
Set up: no tampering with stdin or stdout in this part.
建立Jenkins会话: java -jar jenkins-cli.jar ...
拆卸:在此部分中,请勿篡改stdin或stdout.
Tear down: no tampering with stdin or stdout in this part.
#!/bin/bash
function set_up {
# your set-up code here
}
function tear_down {
# your tear-down code here
}
function main {
# set-up (no stdin, no stdout)
set_up "$@" < /dev/null > /dev/null || exit $?
# establish Jenkins session
java -jar jenkins-cli.jar -blah -blah -blah
# tear-down (no stdin, no stdout)
tear_down "$@" < /dev/null > /dev/null || exit $?
}
main "$@"
但是...为什么?
启动脚本的工作是在主服务器与构建代理之间建立不受干扰的通信通道(通过stdin和stdout).
But... why?
The job of your launch script is to establish an untampered communication channel (via stdin and stdout) between the master and the build agent.
+------------+
"Hello Agent" | |
_ _ ----+ +----
v Hello Agent ->
----+ +----
| |
| | "Hello Master"
----+ +---- _ _
<- Hello Master v
----+ +----
| |
+------------+
launch
script
如果此通信渠道被篡改,詹金斯将无法工作.
If this communication channel is tampered, Jenkins won't work.
+------------+
"Hello Agent" | |
_ _ ----+ +-----------
v Hel PLZ SEND HELP!! t ->
----+ +-----------
| |
| |
----+ +---- | |
^
----+ +----
| |
+------------+
launch
script
如果您不将任何Unix命令送入该命令,则某些Unix命令可能会吞噬"启动脚本的标准输入,因此会破坏"通信通道.考虑以下脚本.
Some Unix commands may "swallow" the stdin of your launch script if you do not pipe anything into that command, and therefore "corrupt" the communication channel. Consider the following script.
#!/bin/bash
function keep_stdin_intact {
printf 'I do not consume any stdin, ' >&2
echo 'and I do not alter the original stdout.' >&2
}
function swallow_stdin {
echo 'I swallow stdin. Did you see any hexdump below?' >&2
read yn # read consumed some stdin
}
echo 'yes' | { keep_stdin_intact; cat -; } | xxd
echo 'yes' | { swallow_stdin; cat -; } | xxd
echo "no you can't now :P" | { swallow_stdin < /dev/null; cat -; } | xxd
-
第一个
yes
被移出并进行了十六进制转储,因为keep_stdin_intact
不会篡改stdin(在这种情况下为是"流).The first
yes
got piped out and hex-dumped, becausekeep_stdin_intact
did not tamper with stdin, in this case, the "yes" stream.第二个
yes
消失了,因为swallow_stdin
消耗了它,所以cat
没什么可负担的,而xdd
没什么可读取的.The second
yes
was gone, becauseswallow_stdin
consumed it, socat
has nothing to cat andxdd
has nothing to read.通过将
/dev/null
传递给stdin-swallowing命令,我们保护了自己的stdin.By piping
/dev/null
to an stdin-swallowing command, we protected our own stdin.ssh
是吞噬您的stdin的邪恶命令之一.ssh
is one of the evil commands that swallow your stdin.假设您要在运行
agent.jar
之前删除构建代理上的某些文件.没有样板,您可能会想写:Let's say you want to remove some files on the build agent before
agent.jar
is run. Without the boilerplate, you may be tempted to write:ssh $OPTIONS "$remote" 'sudo rm -rf /var/log/nginx/*' ssh $OPTIONS "$remote" 'cd $HOME && java -jar agent.jar'
^但这是错误的!第一个
ssh
命令将吞噬您的stdin,并且Jenkins会话将无所读取.^ But this is wrong! The first
ssh
command will swallow your stdin, and the Jenkins session will have nothing to read.第一个
ssh
必须被沉默".传递/dev/null
作为其标准输入.The first
ssh
must be "silenced." Pass/dev/null
as its stdin.ssh $OPTIONS "$remote" 'sudo rm -rf /var/log/nginx/*' < /dev/null ssh $OPTIONS "$remote" 'cd $HOME && java -jar agent.jar'
这篇关于詹金斯奴隶问题-无效的流标头:099EACED的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!