线程" main"中的例外情况java.io.StreamCorruptedException:无效的流标题:0BDAACED

时间:2016-10-05 07:37:29

标签: java jenkins

我正在尝试从master执行jenkins cli命令。

ssh user@192.168.1.2 -C" / usr / bin / java -jar /home/user/slave.jar"

获取以下错误:

<===[JENKINS REMOTING CAPACITY]===>Exception in thread "main" java.io.StreamCorruptedException: invalid stream header: 0BDAACED
  at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:808)
  at java.io.ObjectInputStream.<init>(ObjectInputStream.java:301)
  at hudson.remoting.ObjectInputStreamEx.<init>(ObjectInputStreamEx.java:48)
  at hudson.remoting.ChannelBuilder.makeTransport(ChannelBuilder.java:430)
  at hudson.remoting.ChannelBuilder.negotiate(ChannelBuilder.java:389)
  at hudson.remoting.ChannelBuilder.build(ChannelBuilder.java:310)
  at hudson.remoting.Launcher.main(Launcher.java:528)
  at hudson.remoting.Launcher.runWithStdinStdout(Launcher.java:468)
  at hudson.remoting.Launcher.run(Launcher.java:242)
  at hudson.remoting.Launcher.main(Launcher.java:195)
ERROR: Unexpected error in launching an agent. This is probably a bug in Jenkins
hudson.remoting.RequestAbortedException: java.io.IOException: Unexpected EOF
  at hudson.remoting.Request.abort(Request.java:303)
  at hudson.remoting.Channel.terminate(Channel.java:847)
  at hudson.remoting.SynchronousCommandTransport$ReaderThread.run(SynchronousCommandTransport.java:92)
  at ......remote call to ubuntu-slave(Native Method)
  at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1416)
  at hudson.remoting.Request.call(Request.java:172)
  at hudson.remoting.Channel.call(Channel.java:780)
  at hudson.slaves.SlaveComputer.setChannel(SlaveComputer.java:508)
  at hudson.slaves.SlaveComputer.setChannel(SlaveComputer.java:381)
  at hudson.slaves.CommandLauncher.launch(CommandLauncher.java:131)
  at hudson.slaves.SlaveComputer$1.call(SlaveComputer.java:253)
  at jenkins.util.ContextResettingExecutorService$2.call(ContextResettingExecutorService.java:46)
  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: Unexpected EOF
  at hudson.remoting.ChunkedInputStream.readUntilBreak(ChunkedInputStream.java:99)
  at hudson.remoting.ChunkedCommandTransport.readBlock(ChunkedCommandTransport.java:39)
  at hudson.remoting.AbstractSynchronousByteArrayCommandTransport.read(AbstractSynchronousByteArrayCommandTransport.java:34)
  at hudson.remoting.SynchronousCommandTransport$ReaderThread.run(SynchronousCommandTransport.java:59)
ERROR: Connection terminated
java.io.IOException: Unexpected EOF
  at hudson.remoting.ChunkedInputStream.readUntilBreak(ChunkedInputStream.java:99)
  at hudson.remoting.ChunkedCommandTransport.readBlock(ChunkedCommandTransport.java:39)
  at hudson.remoting.AbstractSynchronousByteArrayCommandTransport.read(AbstractSynchronousByteArrayCommandTransport.java:34)
  at hudson.remoting.SynchronousCommandTransport$ReaderThread.run(SynchronousCommandTransport.java:59)
ERROR: Process terminated with exit code 1

请告诉我可能是什么问题?

1 个答案:

答案 0 :(得分:1)

简短回答

Jenkins的slave.jar通过slave的stdin / stdout与Jenkins服务器通信。你依靠ssh将stdin / stdout传入/传出奴隶。

你不知道在stdin到达奴隶之前篡改stdin的东西,结果通信协议违规会导致你看到的异常。

更长的解释和修复

我想你在jenkins服务器上的shell脚本中有你的问题的ssh命令,它启动了slave,而且这个shell脚本在它之前还有其他命令。因为这就是我的情况,受到jenkins远程处理文档的启发,这表明你可以做一些事情,比如将正确的slave.jar复制到奴隶。

因此我们都使用“通过在服务器上执行命令启动代理”选项来启动从属代理。在我的情况下,我这样做是为了能够使用ssh跳转主机到达奴隶,但这与这个答案无关。

我现在将给出非工作和工作shell脚本的示例,以便在远程节点上启动slave.jar,然后提出可能导致观察到的行为的原因。我使用/ bin / bash作为shell,随意使用其他人。

1)如果奴隶

上已经有slave.jar,这些版本都有效
#!/bin/bash                                                                     
ssh user@host "java -jar /home/user/slave.jar"

#!/bin/bash                                                                     
exec ssh user@host "java -jar /home/user/slave.jar"

两个版本中只有一个命令。这里没有别的东西可以篡改stdin或stdout。在第一个版本中,shell将stdin / stdout转移到ssh命令或从ssh命令转发。在第二个版本中,shell由ssh进程替换,并直接继承其stdin / stdout。两个版本都可以正常工作,第一个版本中的附加shell进程在任何系统上都无关紧要。

2)此版本将slave.jar从服务器上的某个位置复制到从属服务器,然后在服务器上执行

#!/bin/bash
scp -q /some/location/slave.jar user@host:.
exec ssh user@host "java -jar /home/user/slave.jar"

当然,只有在服务器上有/some/location/slave.jar时才有效。

3)此版本尝试在启动从属代理之前对从属进行一些额外的清理。

#!/bin/bash
ssh user@host "rm -rf /home/user/tmp/jenkins"
exec ssh user@host "java -jar /home/user/slave.jar"

奴隶上的/ home / user / tmp / jenkins位置只是一个例子。 超过4分钟后此版本失败。使用问题的确切错误消息。失败不是由/ home / user / tmp / jenkins中遗漏的重要原因引起的,正如您将在下一个示例中看到的那样:

4)使示例3工作的不同方法

#!/bin/bash
ssh user@host "rm -rf /home/user/tmp/jenkins" </dev/null
exec ssh user@host "java -jar /home/user/slave.jar"

#!/bin/bash
exec ssh user@host "rm -rf /home/user/tmp/jenkins && java -jar /home/user/slave.jar"

在第一个修复中,我们确保与从站通信的stdin不会转发到远程rm命令。 rm没有读取它的stdin,但显然ssh不知道这个并从它自己的stdin缓冲一些字节并将它们转发到远程命令以防它需要它?这可以通过将/ dev / null作为stdin转发到rm命令而不是目标为从通信的stdin来解决。

在第二个修复程序中,只使用了一个ssh命令,rm命令再次从stdin读取任何内容,slave.jar接收到未被禁用的流。