【问题标题】:Gitlab CI job hangs when ssh command is run运行 ssh 命令时 Gitlab CI 作业挂起
【发布时间】:2022-01-04 15:32:46
【问题描述】:

作业通过 SSH 在其服务器上运行脚本(打开 ssh)。脚本执行成功,因此连接成功。 问题是它永远不会断开连接。永久保持运行状态,最后超时终止(如果之前没有手动停止)。

失败的命令是:

- ssh -o StrictHostKeyChecking=no root@server -p 22 '/home/script.sh'

我可以在服务器上看到脚本如何正确运行。 ssh 连接似乎永远不会关闭。在该命令之后,作业不会执行任何其他操作,并且会无限加载。

当脚本从服务器本身执行时,它也可以正常工作。


我已经尝试过的事情

我尝试过以不同方式添加exit 命令

- ssh -o StrictHostKeyChecking=no root@server -p 22 '/home/script.sh && exit'

- ssh -o StrictHostKeyChecking=no root@server -p 22 '/home/script.sh && exit 0'

- ssh -o StrictHostKeyChecking=no root@server -p 22 '/home/script.sh ; exit'

- ssh -o StrictHostKeyChecking=no root@server -p 22 '/home/script.sh ; exit 0'

我也试过在后面加一行

- ssh -o StrictHostKeyChecking=no root@server -p 22 '/home/script.sh'
- exit

我也试过添加后台运行命令&

- ssh -o StrictHostKeyChecking=no root@server -p 22 '/home/script.sh &'
- exit

- ssh -o StrictHostKeyChecking=no root@server -p 22 '/home/script.sh &'

- ssh -o StrictHostKeyChecking=no root@server -p 22 '/home/script.sh & ; exit'

- ssh -o StrictHostKeyChecking=no root@server -p 22 '/home/script.sh & ; exit 0'

我也试过杀死 ssh 进程

# add this line after the problematic (in its diferent ways) 
 - eval $(ssh-agent -k)

完整的脚本gitlab-ci.yml

# This file is a template, and might need editing before it works on your project.
# Build JAVA applications using Apache Maven (http://maven.apache.org)
# For docker image tags see https://hub.docker.com/_/maven/

# This template uses jdk8 for verifying and deploying images
image: maven:3.6.0-jdk-8

stages:
  - build
  - deploy
  - notify
  
build:
  stage: build
  only:
    - dev
  script: "mvn clean install -Dactive.profile=dev -DskipTests -B"
  artifacts:
    paths:
      - target/*.jar
      - notifydeploy.sh
      - $DEV_SSH

deploy:
  stage: deploy
  only:
    - dev
  before_script:
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    # Run ssh-agent (inside the build environment)
    - eval $(ssh-agent -s)
    # Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
    - ssh-add <(echo "$DEV_SSH")
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
  script:
    - scp -P 22 ./target/*.jar root@server:/home
    - ssh -o StrictHostKeyChecking=no root@server -p 22 '/home/script.sh'
    - eval $(ssh-agent -k)

notify_fail:
  stage: notify
  allow_failure: true
  only:
    - dev
  when: on_failure
  script:
    - echo "FAIL"
    
notify_success:
  stage: notify
  allow_failure: true
  only:
    - Deploy_to_dev03
  script:
    - chmod +x ./notifydeploy.sh
    - ./notifydeploy.sh

当 gitlab 进程正在等待挂起它的命令时,如果从服务器执行相同的脚本,则作业被解锁并正确结束...

使用ps aux | grep script.sh 在服务器上查找进程时,当作业执行时会显示它,但随后它会消失,因此它不会挂在服务器上。

对此有任何解决方案吗?我想不出还有什么可以尝试的..

script.sh 是这样的:

#!/bin/bash

status_code=$(curl --write-out %{http_code} --silent --output /dev/null http://server/url/)
status_code_n=$(curl --write-out %{http_code} --silent --output /dev/null http://localhost:8761)
#Si no es igual a 404 es que esta funcionando
if [[ "$status_code" == 200  &&  "$status_code_n" == 200 ]] ; then  
    echo "Estatus c $status_code"  
    echo "Estatus n $status_code_n"
    pkill -f jar-process
    sleep 1 
    /usr/bin/java -jar -Dspring.profiles.active=dev /home/jar-process*.jar &
    sleep 1
    status_code_t=$(curl --write-out %{http_code} --silent --output /dev/null http://localhost:8090/api/)
    if [[ "$status_code_t" == 401 ]] ; then  
        echo "Estatus $status_code_t (401 is OK)"
        echo "La API se ha desplegado correctamente"
        exit 0
    else
        echo "Estatus $status_code_t"
        echo "Se ha producido algun error al desplegar"
        exit 1
    fi
else
    echo "Estatus c $status_code"
    echo "Estatus n $status_code_n"
    exit 1
fi

【问题讨论】:

  • /home/script.sh 是做什么的?它是否启动任何继续在后台运行的进程?在您的问题中包含 /home/script.sh 会很有帮助。
  • 谢谢!只需添加它@Kenster

标签: ssh gitlab gitlab-ci gitlab-ci-runner openssh


【解决方案1】:

简短的回答是为脚本的 java 命令重定向标准文件描述符(标准输入、输出和错误),如下所示:

/usr/bin/java ... /home/jar-process*.jar > /dev/null 2>&1 < /dev/null &

这可以防止java进程继承脚本的标准输出等等。这就是阻止 ssh 关闭连接的原因。

更长的答案:当您运行 ssh 命令时,例如:

ssh user@remote '/home/script.sh'

远程 ssh 服务器将创建一组管道来充当远程命令的标准输入、输出和错误。启动命令后,ssh 服务器将保持通道打开,直到在与远程命令的标准输出关联的管道上看到文件结束条件。

您的脚本正在启动一个应该在脚本退出后继续运行的进程。该进程继承了 ssh 创建的管道作为其标准描述符。该进程理论上可以写入其标准输出,因此 ssh 服务器在进程退出或关闭其标准输出之前不会在标准输出管道上看到文件结束条件。

您可以像这样重定向整个脚本的输出:

ssh user@remote '/home/script.sh >/dev/null 2>&1 < /dev/null'

但是,在您的情况下,脚本在失败时似乎会产生错误消息。重定向整个脚本的输出会阻止您看到错误消息。

【讨论】:

  • 效果很好!谢谢!就我而言,我需要在后台运行 ssh 端口转发。在没有输入/输出重定向的情况下挂起。
猜你喜欢
  • 2017-01-09
  • 1970-01-01
  • 2019-05-13
  • 2017-04-01
  • 2020-06-28
  • 2022-08-06
  • 2022-11-08
  • 1970-01-01
  • 2022-08-14
相关资源
最近更新 更多