linux Jenkins Slave问题-无效的流头:099 EACED

jgwigjjp  于 12个月前  发布在  Linux
关注(0)|答案(1)|浏览(117)

Jenkins 2.7.4安装在RedHat Server中,Linux Slave通过选择"Launch agent via execution of command on master"选项进行配置。我们创建了一个Shell脚本,它在Jenkins版本2.7.4中运行良好。
现在我们将Jenkins升级到2.121.1。
<====[JENKINS REMOTING CAPACITY]===>线程"main"出现异常java. io. StreamCorruptedException:无效的流头:099EACED at java. io. ObjectInputStream. readStreamHeader(ObjectInputStream.java:808),位于java.io.ObjectInputStream。(ObjectInputStream.java:301),位于hudson.remoting.ObjectInputStreamEx。(ObjectInputStreamEx.java:48),位于hudson. remoting. MapelBuilder. makeTransport(java:478)在hudson. remoting. remotelBuilder. negotiate(java:433)在www.example.com(java:354)在hudson. remoting. Launcher. main(Launcher.java:743)位于hudson. remoting. Launcher. runWithStdinStdout(Launcher.java:691),网址:www.example.com(Launcher.java:373)at hudson. remoting. Launcher. main(Launcher.java:283)错误:连接终止错误:hudson.remoting.ChannelBuilder.buildhudson. remoting. ChunkedInputStream. readUntilBreak(ChunkedInputStream.java:99)上的意外错误hudson. remoting. ChunkedCommandTransport. readBlock(ChunkedCommandTransport.java:39)上的错误www.example.com(AbstractSynchronousByteArrayCommandTransport.java:35)上的错误hudson. remoting. SynchronousCommandTransport $ReaderThread.run(SynchronousCommandTransport.java:63)另外:hudson. remoting. Channel $CallSiteStackTrace:hudson.remoting.Launcher.run46)at jenkins.security.ImpersonatingExecutorService$2.call(ImpersonatingExecutorService.java:71)at www.example.com(Unknown Source)at java. util. concurrent. ThreadPoolExecutor. runWorker(Unknown Source)at java. util. concurrent. ThreadPoolExecutor $www.example.com(Unknown Source)at www.example.com(Unknown Source)导致:hudson. remoting. RequestAbortedException at hudson. remoting. Request. abort(Request.java:340)at hudson. remoting. Channel. terminate(Requestel.java:1038)at hudson. remoting. SynchronousCommandTransport $ReaderThread.run(SynchronousCommandTransport.java:96)
如果我在Manage Jenkins-> Configure Security中禁用SSHD端口,那么我就可以启动我的slave。但是在我的脚本中,我将使用Jenkins-cli.jar触发一个作业,将二进制文件从master复制到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我收到一条消息,

"WARNING: No header 'X-SSH-Endpoint' returned by Jenkins"

字符串
我也试过在jenkins-cli.jar命令中将-ssh替换为-http,
java -jar jenkins-cli.jar -s http://localhost:8080 -http -auth username:60b3450a883a2519592af84cdcd0d224 build $CI_JOB -s -p SLAVE_REGEX=$SLAVEHOST
它会触发任务。同样无法启动从机,
<=[JENKINS REMOTING CAPACITY]=>线程"main"出现异常java. io. StreamCorruptedException:无效的流头:099FACED at java. io. ObjectInputStream. readStreamHeader(ObjectInputStream.java:808),位于java.io.ObjectInputStream。(ObjectInputStream.java:301),位于hudson.remoting.ObjectInputStreamEx。(ObjectInputStreamEx.java:48),位于hudson. remoting. MapelBuilder. makeTransport(java:478)在hudson. remoting. remotelBuilder. negotiate(java:433)在www.example.com(java:354)在hudson. remoting. Launcher. main(Launcher.java:743)位于hudson. remoting. Launcher. runWithStdinStdout(Launcher.java:691),网址:www.example.com(Launcher.java:373)在hudson. remoting. Launcher. main(Launcher.java:283)用法:hudson.remoting.ChannelBuilder.build
如何解决这个问题

zaq34kh6

zaq34kh61#

stdin不变,stdout不变

我相信你的脚本中有东西在篡改标准输入。
您的脚本应该将完整的、未更改的stdin流传递给Jenkins代理进程。

通用解决方案

OP建立Jenkins会话的命令与我的命令不同,但无论如何,您应该将启动脚本分为3个主要部分:

**设置:**在这一部分不篡改stdin或stdout。
建立Jenkins会话:java -jar jenkins-cli.jar ...
**Tear down:**在这一部分不篡改stdin或stdout。

#!/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)。

+------------+
"Hello Agent" |            |
   _ _    ----+            +----
    v               Hello Agent  ->
          ----+            +----
              |            |
              |            |  "Hello Master"
          ----+            +----   _ _
       <-  Hello Master             v
          ----+            +----
              |            |
              +------------+
                  launch
                  script


如果这个通讯频道被篡改了Jenkins就不能用了

+------------+
"Hello Agent" |            |
   _ _    ----+            +-----------
    v            Hel PLZ SEND HELP!! t  ->
          ----+            +-----------
              |            |
              |            |  
          ----+            +----   | |
                                    ^
          ----+            +----
              |            |
              +------------+
                  launch
                  script


如果你不把任何东西通过管道传输到某些Unix命令中,它可能会“吞下”你的启动脚本的stdin,从而“破坏”通信通道。

#!/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,在本例中是“yes”流。
  • 第二个yes已经消失了,因为swallow_stdin消耗了它,所以cat没有什么可cat的,xdd没有什么可读的。
  • 通过将/dev/null通过管道传输到stdin-swallowing命令,我们保护了自己的stdin。

ssh怎么了?

ssh是吞噬你的标准输入的邪恶命令之一。
假设您想在运行agent.jar之前删除构建代理上的一些文件。如果没有样板文件,您可能会这样写:

ssh $OPTIONS "$remote" 'sudo rm -rf /var/log/nginx/*'
ssh $OPTIONS "$remote" 'cd $HOME && java -jar agent.jar'


^但这是错误的!第一个ssh命令会吞下你的stdin,Jenkins会话将没有任何内容可读。
第一个ssh必须“静默”。将/dev/null作为其标准输入。

ssh $OPTIONS "$remote" 'sudo rm -rf /var/log/nginx/*' < /dev/null
ssh $OPTIONS "$remote" 'cd $HOME && java -jar agent.jar'

相关问题