Проблема с подчиненным Jenkins - неверный заголовок потока: 099EACED
Jenkins 2.7.4 был установлен на сервере RedHat, а подчиненные Linux настроены с помощью опции "Запустить агент через выполнение команды на главном". Мы создали скрипт Shell, и он отлично работает в версии 2.7.4 Jenkins.
Теперь мы обновили Jenkins до 2.121.1. Теперь тот же скрипт выдает ошибку
<===[JENKINS REMOTING CAPACITY]===>Исключение в потоке "main" java.io.StreamCorruptedException: недопустимый заголовок потока: 099EACED в java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:808) в java.io.ObjectInputStream.(ObjectInputStream.java:301) в hudson.remoting.ObjectInputStreamEx.(ObjectInputStreamEx.java:48) в hudson.remoting.ChannelBuilder.makeTransport(ChannelBuilder.java:478) в hudson.remoting.ChannelBilder (javaBilder):433) в hudson.remoting.ChannelBuilder.build(ChannelBuilder.java:354) в hudson.remoting.Launcher.main(Launcher.java:743) в hudson.remoting.Launcher.runWithStdinStdout(Launcher.java:691) в h.remoting.Launcher.run(Launcher.java:373) at hudson.remoting.Launcher.main(Launcher.java:283) ОШИБКА: соединение прервано ОШИБКА: непредвиденная ошибка при запуске агента. Вероятно, это ошибка в Jenkins java.io.IOException: неожиданное EOF в hudson.remoting.ChunkedInputStream.readUntilBreak(ChunkedInputStream.java:99) в hudson.remoting.ChunkedCommandTransport.readBlock(ChunkedCommandTransport.java39): AbstractSynchronousByteArrayCommandTransport.read(AbstractSynchronousByteArrayCommandTransport.java:35) в hudson.remoting.SynchronousCommandTransport$ReaderThread.run(SynchronousCommandTransport.java:63) ОШИБКА. Процесс завершен с ошибочным выходом. readUntilBreak (ChunkedInputStream.java:99) по адресу hudson.remoting.ChunkedCommandTransport.readBlock(ChunkedCommandTransport.java:39) по адресу hudson.remoting.AbstractSynchronousByteArrayCommandTransport.read(AbstractSynchronousThromTransportHransTromTransport).java: 63) Также: hudson.remoting.Channel$CallSiteStackTrace: удаленный вызов rtt-ci-euhrhd0036vdeas at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1741) в hudson.remoting.Request.call(Request.java:202) в hudson.remoting.Channel.call(Channel.java:954) в hudson.slaves.SlaveComputer.setChannel(SlaveComputer.java:549) в hudson.slaves.SlaveComputer.setChannel(SlaveComputer.java:416) в hudson.slaves.CommandLauncher.launch(CommandLauncher.java:15.slaves $1SudSudSududSudud.SlaudS $udsSlaSudSudSududSududSududSududSaudSlaSudSudSudSudSud = 1 $ -) в h.call(SlaveComputer.java:288) по адресу jenkins.util.ContextResettingExecutorService$2.call(ContextResettingExecutorService.java:46) по адресу jenkins.security.ImpersonatingExecutorService$2.call(ImpersonatingExecutorService.javaurtil.Future. at ю).71 выполнить (неизвестный источник) в java.util.concurrent.ThreadPoolExecutor.runWorker(неизвестный источник) в java.util.concurrent.ThreadPoolExecutor$Worker.run(неизвестный источник) в java.lang.Thread.run(неизвестный источник) Причина: hudson.remoting.RequestAbortedException в hudson.remoting.Request.abort(Request.java:340) в hudson.remoting.Channel. прекратить (Channel.java:1038) в hudson.remoting.SynchronousCommandTransport$ReaderThread.run(SynchronousCommandTransport.java:96)
Если я отключу SSHD-порт в "Управление Jenkins -> Настройка безопасности", тогда я смогу запустить свое ведомое устройство. Но в моем сценарии я вызову одно задание, используя 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
Я получаю сообщение как
"WARNING: No header 'X-SSH-Endpoint' returned by Jenkins"
и сборка не срабатывает. Я также попытался заменить -ssh на -http в команде jenkins-cli.jar,
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 в java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:808) в java.io.ObjectInputStream.(ObjectInputStream.java:301) в hudson.remoting.ObjectInputStreamEx.(ObjectInputStreamEx.java:48) в hudson.remoting.ChannelBuilder.makeTransport(ChannelBuilder.java:478) в hudson.remoting.ChannelBilder (javaBilder):433) в hudson.remoting.ChannelBuilder.build(ChannelBuilder.java:354) в hudson.remoting.Launcher.main(Launcher.java:743) в hudson.remoting.Launcher.runWithStdinStdout(Launcher.java:691) в h.remoting.Launcher.run(Launcher.java:373) at hudson.remoting.Launcher.main(Launcher.java:283) usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port] [-e escape_char] [-F configfile] [-i identity_file] [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port] [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]] [user@]hostname [command] ERROR: Unexpected error in launching an agent. This is probably a bug in Jenkins ERROR: Connection terminated java.io.IOException: Unexpected EOF
Как исправить эту проблему
1 ответ
Неизмененный стандартный вывод, неизмененный стандартный вывод
Я полагаю, что что-то в вашем сценарии вмешивается в stdin.
Ваш сценарий должен передать весь неизмененный поток stdin процессу агента Jenkins.
Универсальное решение
Команда OP, устанавливающая сеанс Jenkins, отличается от моей, но независимо от этого вы должны разбить свой сценарий запуска на 3 основные части:
Настройка: не вмешиваться в stdin или stdout в этой части.
Установить сессию Дженкинса: java -jar jenkins-cli.jar ...
Снесите: не вмешивайтесь в 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
Если этот канал связи подделан, Дженкинс не будет работать.
+------------+
"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
ушел, потому чтоswallow_stdin
потребляется, такcat
не имеет ничего к кошке иxdd
читать нечего.По трубам
/dev/null
к команде проглатывания стандартного ввода мы защитили свой собственный стандартный ввод.
Что случилось с SSH?
ssh
это одна из злых команд, которые проглатывают ваш стандартный.
Допустим, вы хотите удалить некоторые файлы в агенте сборки до того, как agent.jar
это запустить. Без шаблона вы можете написать:
ssh $OPTIONS "$remote" 'sudo rm -rf /var/log/nginx/*'
ssh $OPTIONS "$remote" 'cd $HOME && java -jar agent.jar'
^ Но это не так! Первый ssh
команда проглотит ваш стандартный ввод, и сеансу Дженкинса нечего будет читать.
Первый ssh
должно быть "замолчать". Проходить /dev/null
как его стандарт.
ssh $OPTIONS "$remote" 'sudo rm -rf /var/log/nginx/*' < /dev/null
ssh $OPTIONS "$remote" 'cd $HOME && java -jar agent.jar'