前段时间实现了java将jar包打包成RPM包,并启动。RPM里jar包的启动仍然是采用java -jar 的方式进行启动。这种方式仅适用于单个jar包并且配置较少的方式。近期需要将SkyWalking的服务包打包成RPM进行运行,当需要打包的文件过多,就需要对打包方式进行修改。
1. 打包命令
编写rpm-tar.sh,内容如下:
#!/bin/bash
# 必选参数 -p 项目名称; -n 包名称,包名称为Service名; -t 压缩包的名称
#将需要打包的所有文件压缩成一个tar包,将tar包放入打包命令所在文件夹,执行如下命令
# 例如 ./rpm-tar.sh -p test -n test-demo1 -z test-demo1.tar.gz
######################################################################################
#参数区域
help(){
echo "Useage:"
echo "rpmbuild.sh [-p PROJECT_NAME] [-n PACKAGE_NAME] [-t TAR_NAME] "
echo "Description:"
echo "-r delete tmp_file after rpmbuild"
exit 0
}
while getopts 'p:n:t:hr' OPT; do
case $OPT in
p) PROJECT_NAME="$OPTARG";;
n) PACKAGE_NAME="$OPTARG";;
t) TAR_NAME="$OPTARG";;
r) DELETE_FLAG="false";;
h) help;;
?) echo "error:unknown flag"
echo "==================="
help
exit 1
esac
done
if [$# -eq 0 ];then
echo "error:no argument"
echo "=================="
help
exit 1
fi
#######################################################################################
#变量区域
#1.获取当前目录
PRG="$0"
PRGDIR=$(dirname "$PRG")
[ -z "$OAP_HOME" ] && OAP_HOME=$(cd "$PRGDIR" > /dev/null || exit 1; pwd)
#构建过程中的临时目录
app_dir=%{buildroot}/data/$PROJECT_NAME/$PACKAGE_NAME
service_dir=%{buildroot}/%{_unitdir}
#######################################################################################
#函数区域
#构建rpm
rpmbuild_start(){
#拷贝tar包至构建目录
cp $TAR_NAME ~/rpmbuild/SOURCES/
#打包
rpmbuild -bb ~/rpmbuild/SPECS/$PACKAGE_NAME.spes > rpmbuild.log 2>&1
if[ $? -ne 0 ];then
echo "构建rpm包失败,请查看rpmbuild.log"
else
echo -e "构建rpm包成功\nls -lht ~/rpmbuild/RPMS/noarch" &&
ls -lht ~/rpmbuild/RPMS/noarch
fi
}
#检查rpmbuild是否已安装
check_rpmbuild_install(){
if ! type rpmbuild >/dev/null 2>&1;then
echo "检测到rpmbuild未安装,开始安装"
yum install -y rpm-build >dev/null 2>&1 &&
echo "rpmbuild安装完成"&&
mkdir -p ~/rpm-build/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
else
echo "检测到rpmbuild已安装" &&
mkdir -p ~/rpm-build/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
fi
}
构建service文件
rpmbuild_service(){
echo "开始构建systemd服务文件"
cat <<EOF >~/rpm-build/SOURCES/$SERVICE_NAME.service
[Unit]
Description=interaction
After=network-online.target
[Service]
Type=simple
workingDirectory=/data/$PROJECT_NAME/$PACKAGE_NAME
EXEC_START=/data/$PROJECT_NAME/$PACKAGE_NAME/bin/start.sh
RestartSec=10
StartLimitInterval=0
User=root
Group=root
[Install]
WanteBy=multi-user.target
EOF
}
#构建spec文件
rpm-build_spec(){
echo "开始构建,请稍后..."
cat <<EOF >~/rpm-build/SPECS/$PACKAGE_NAME.sepc
Name: $PACKAGE_NAME
Version: 0.0.1
Release: 1%{?dist}
Summary: Rpm package
Lincense: ASL 2.0
Source0: $SERVICE_NAME.service
Source1: $TAR_NAME
BuildRequires: systemd
%{?systemd_requires}
BuildArch: noarch
%description
%{summary}
%define debug_package %{nil}
%define __jar_repack %{nil}
%grep
%build
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}
mkdir -p $app_dir
mkdir -p ${buildroot}/usr/lib/systemd/system/
cp %{SOURCE0} $service_dir
tar -xf %{SOURCE1} -C $app_dir
%files
%defattr(755,root,root,-)
%dir /data/$PROJECT_NAME/$PACKAGE_NAME
/usr/lib/systemd/system/$SERVICE_NAME.service
/data/$PROJECT_NAME/$PACKAGE_NAME/*
%post
%systemd_post $SERVICE_NAME.service
%{_bindir}/systemctl enable $SERVICE_NAME.service
%pretun
%systemd_postun_with_restart $SERVICE_NAME.service
EOF
}
delete_tmp_file(){
if ["$DELETE_FLAG" != "false" ]; then
echo "删除临时文件"
rm -rf ~/rpm-build/SOURCES/* &&
rm -rf ~/rpm-build/SPECS/*
fi
}
###########################################################################################################
#脚本执行入口
rpm-build_main(){
check_rpmbuild_install&&
rpmbuild_service&&
rpmbuild_spec&&
rpmbuild_start&&
delete_tmp_file
}
rpm-build_main
2. 采用sh命令启动问题解决
上述例子中,RPM包的启动命令如下,仍然采用原有的sh脚本启动
EXEC_START=/data/$PROJECT_NAME/$PACKAGE_NAME/bin/start.sh
启动异常
# 启动
systemctl start test-demo1
# 查看启动状态,发现状态为dead
systemctl status test-demo1
后续考虑猜想,可能是因为rpm执行完启动命令之后,进程会被关闭(具体原因不了解)。
解决方法:
修改原有包的启动命令最后一行,增加如下:
tail -f /dev/null
增加如下命令之后,使用 systemctl start test-demo1 可以正常启动。