AzureDevOps无法执行脚本程序

标签: Azure 分类: 软件 创建时间:2019-11-01 08:58:13 更新时间:2025-09-26 04:44:38

我在代理机器上通过maven生成了jar包,通过ssh文件复制的方式,将jar包上传到部署服务器上。具体方法可以参考另一篇文章:Azure的DevOps发布和打包Springboot程序,然后在部署服务器上执行java -jar程序,这是可以执行的。但是为了能在后台执行java -jar,我绞尽了脑汁,想尽了方法,还是不可以。因为虽然可以在命令行中编写java -jar执行成功这个jar包,但是命令行退出之后,jar包也就退出了,所以我需要在后台运行jar包。
命令行脚本编写如下:

1
2
cd /home/zhenglc/proj/PhMapServer;chmod + x ./auto_run.sh;./auto_run.sh;

在远程服务器上的/home/zhenglc/proj/PhMapServer目录下的auto_run.sh 脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#!/bin/bash

# 结束进程,这里的 kill -9 {} 2
ps -ef | grep PhMapServer | grep -v grep | cut -c 9-14 | xargs -I {} kill -9 {} 2>&1;

cd `dirname $0`
## 获取jar包
jarpath=`ls -t *.jar | head -1`
echo ${jarpath}
echo "准备执行"
## 执行jar包
## nohup java -jar ${jarpath} -Dspring.config.location=application.yml
source /etc/profile
setsid /usr/java/jdk1.8.0_201/bin/java -jar /home/zhenglc/proj/PhMapServer/PhMapServer-0.0.1-SNAPSHOT.jar -Dspring.config.location=application.yml >>out.log 2>&1 &

问题出在setsid这句上,我直接通过xshell连接到远程服务器上,执行这个setsid命令,或者上面的那个nohup命令,都可以在后台创建java进程,甚至我直接通过xshell输入./auto_run.sh(先要进入那个目录中),都可以创建一个后台的springboot进程。

奇怪的是,我通过Azure的devOps添加命令行任务的方式去执行这个auto_run.sh脚本,死活都创建不出一个springboot进程,但依然会显示命令执行成功。更加可气的是,脚本已经执行了,而且也输出了“准备执行”,但就是没有springboot的java进程。

郁闷啊,尝试了n多种方法。

参考文章:
1.Jenkins SSH 远程执行 Shell 脚本
2.远程执行命令
3.ssh远程执行nohup命令不退出
4.ssh 远程不能执行JAVA启动脚本
5.Linux 后台运行 java -jar 执行jar包
6.Linux后台运行Jar方法
7.nohup运行shell脚本kill命令后代码不执行
8.无法在Azure管道上执行shell脚本
9.SSH Deployment task
10.如何理解Linux shell中的“2>&1” 2>&1表明将文件描述2(标准错误输出)的内容重定向到文件描述符1(标准输出),为什么1前面需要&?当没有&时,1会被认为是一个普通的文件,有&表示重定向的目标不是一个文件,而是一个文件描述符。


刚刚得到消息:“是的,这是默认行为。VSTS将关闭构建/部署完成时在执行期间启动的所有进程。”,像Jenkins也有同样的问题,不过晚上解决的方法还是有很多的,但是Azure DevOps就很可怜了,只是有人说这是默认策略,但是从不说这如何解决。

参考文章:
10.后台进程在部署组阶段结束后终止
11.Background process terminates after the deployment group phase ended
12.解决jenkins启动完会kill掉的衍生进程
13.jenkins默认在build结束后会kill掉所有的衍生进程

还有一些其他的文章
14.通过Azure自动化在Azure Linux VM上运行SSH命令
15.通过Azure自动化在Azure Linux VM上运行SSH命令

使用ssh连接,执行已下命令:

1
cd /home/zhenglc/proj/PhMapServer;chmod + x ./auto_run.sh;BUILD_ID=DONTKILLME nohup ./auto_run.sh &

出现了错误,无法执行脚本。

临时解决方案,auto_run.sh脚本内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/sh

source /etc/profile
. /etc/profile

## 结束进程
## ps -ef | grep PhMapServer | grep -v grep | cut -c 9-14 | xargs -I {} kill -9 {} 2>&1

## cd `dirname $0`
## 获取jar包
## jarpath=`ls -t /home/zhenglc/proj/PhMapServer/*.jar | head -1`
## echo ${jarpath}
echo "准备执行"
## 执行jar包
## nohup java -jar ${jarpath} -Dspring.config.location=application.yml
## source /etc/profile
setsid /usr/java/jdk1.8.0_201/bin/java -jar /home/zhenglc/proj/PhMapServer/PhMapServer-0.0.1-SNAPSHOT.jar -Dspring.config.location=application.yml >>out.log 2>&1 &

ssh远程任务内容:

1
sh /home/zhenglc/proj/PhMapServer/auto_run.sh

使用了绝对路径,把一些变量也删掉了。

这样就执行成功了。具体的还需要进一步研究

其他问题:
(1) ssh脚本不连续,只能使用绝对路径执行脚本程序
按提示内容,在填写ssh任务里面的命令行中

1
2
3
4
5
#!/bin/sh -l
cd /home/zhenglc/proj/PhMapServer
pwd
./stop.sh
./start.sh

一行一行的填写相关脚本

结果执行不正确,找不到文件./stop,也就是没有进入到/home/zhenglc/proj/PhMapServer/ 目录,但是远程计算机上确实是存在这个目录且存在这个文件的,即便是使用pwd输出当前目录,也是出现了/***这样的字样,也不是当前目录

通过执行内联脚本,并且要使用绝对路径的方式才能正确的执行脚本

参考文章:
1.shell脚本中无法使用cd的问题原因及解决方法
2.Jenkins——应用篇——插件使用——Publish over SSH
3.jenkin执行shell脚本,找不到命令
4.shell脚本中cd命令无效的解决方案

解决方法

(1) 编写start.sh脚本文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/sh

source /etc/profile

## 结束进程
#ps -ef | grep PhMapServer | grep -v grep | cut -c 9-14 | xargs -I {} kill -9 {}

SHELL_FOLDER='/home/zhenglc/proj/PhMapServer'

## 获取jar包
jarpath=` ls -t ${SHELL_FOLDER}/*.jar | head -1 `

echo "准备执行"
## 执行jar包
## nohup java -jar ${jarpath} -Dspring.config.location=application.yml > /dev/null 2>&1 &
## source /etc/profile
setsid java -jar ${jarpath} -Dspring.config.location=application.yml >>out.log 2>&1 &

编写停止stop.sh脚本文件

1
2
3
4
5
#!/bin/sh

## 结束进程
pkill -f PhMapServer 2>&1 &

(2)azure中使用ssh任务执行脚本,使用绝对路径执行:

1
sh /home/zhenglc/proj/PhMapServer/stop.sh;sh /home/zhenglc/proj/PhMapServer/start.sh

绝对路径执行脚本,这个很重要

文章目录
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件(ititchuan@gmail.com)通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
ititchuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。