把linux可执行程序做成一个系统服务

在linux系统启动的时候,我们可以看到很多服务性程序一个接一个的被启动(就是那些后面有一个兰色[OK]的行),这些在后台运行的程序为我们使用计算机起了很重要的作用,以这种方式运行的程序有以下特点:
1、开机启动,关机停止(废话!关机了还运行啊???)
2、后台运行
3、通过service 命令控制或查看对应的程序的运行状态
恩,不错,那怎么把我们自己编制的程序做成这样的一个服务呢?废话少说,主要分以下3步,本文实例以搭建 chfs 服务为例:

注意:本文中的 chfs 可执行文件和chfs.ini 文件假设放置在根目录 / 中,如不同可自行修改相应代码

1、把可执行程序放到一个linux系统可以找到的地方。

在linux命令提示符下输入env ,回车后可看到环境变量,里面有一项PATH的,对,这项里所指定的目录都是系统可找到的地方,把我们的可执行程序放入其中的一个目录下即可,我们一般放在/usr/sbin/目录下(放什么有放什么的地方,最好不要乱放)。

2、在目录/etc/init.d/ 下,新建一个以服务名为文件名的文件。

如果我们打开目录/etc/init.d/,看到的文件其实都是服务程序文件,每个文件的内容都大同小异,我们会看到,这里的文件在文件结构上几乎是一样 的。几乎每个文件 都有start、stop、restart和status这样的标志,对,我们新建的这个文件也具有相同的结构,只是在这些标志内部把相应的可执行程序换 成我 们自己的可执行程序即可,知道怎么做了吗?那就是:复制——修改——保存。

举例:以安装 chfs 服务为例,新建一个名为 chfs 的文件,内容如下,可自行修改

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
ProgramName="chfs"
ProgramPath="/"
NAME=chfs
BIN=${ProgramPath}/${NAME}
CONFIGFILE=${ProgramPath}chfs.ini
SCRIPTNAME=/etc/init.d/${NAME}
version="1.1"
program_version=`${BIN} --version`
RET_VAL=0

[ -x ${BIN} ] || exit 0
strLog=""
fun_clangcn()
{
    echo ""
    echo "+---------------------------------------------------------+"
    echo "|     Manager for ${ProgramName}, Author Brokenway      |"
    echo "+---------------------------------------------------------+"
    echo ""
}

fun_check_run(){
    PID=`ps -ef | grep -v grep | grep -i "${BIN}" | awk '{print $2}'`
    if [ ! -z $PID ]; then
        return 0
    else
        return 1
    fi
}
fun_load_config(){
    if [ ! -r ${CONFIGFILE} ]; then
        echo "config file ${CONFIGFILE} not found"
        return 1
    fi
}
fun_start()
{
    if [ "${arg1}" = "start" ]; then
      fun_clangcn
    fi
    if fun_check_run; then
        echo "${ProgramName} (pid $PID) already running."
        return 0
    fi
    fun_load_config
    echo -n "Starting ${ProgramName}(${program_version})......"
    ${BIN} --file=${CONFIGFILE} >/dev/null 2>&1 &
    sleep 1
    if ! fun_check_run; then
        echo " failed"
        return 1
    fi
    echo " Success"
    echo "${ProgramName} (pid $PID)is running."
    return 0
}

fun_stop(){
    if [ "${arg1}" = "stop" ] || [ "${arg1}" = "restart" ]; then
      fun_clangcn
    fi
    if fun_check_run; then
        echo -n "Stoping ${ProgramName} (pid $PID)... "
        kill $PID
        if [ "$?" != 0 ] ; then
            echo " failed"
            return 1
        else
            echo " done"
        fi
    else
        echo "${ProgramName} is not running."
    fi
    return 0
}
fun_restart(){
    fun_stop
    fun_start
}
fun_status(){
    PID=`ps -ef | grep -v grep | grep -i "${BIN}" | awk '{print $2}'`
    if [ ! -z $PID ]; then
        echo "${ProgramName} (pid $PID) is running..."
    else
        echo "${ProgramName} is stopped"
        exit 0
    fi
}
checkos(){
    if   grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then
        OS=CentOS
    elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then
        OS=Debian
    elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then
        OS=Ubuntu
    elif grep -Eqi "Alpine" /etc/issue || grep -Eq "Alpine" /etc/*-release; then
        OS=Alpine
    else
        echo "Not support OS, Please reinstall OS and retry!"
        return 1
    fi
}
fun_config(){
    if [ -s ${CONFIGFILE} ]; then
        vi ${CONFIGFILE}
    else
        echo "${ProgramName} configuration file not found!"
        return 1
    fi
}
fun_version(){
    echo "${ProgramName} version ${program_version}"
    return 0
}
fun_help(){
    ${BIN} --help
    return 0
}

arg1=$1
[  -z ${arg1} ]
case "${arg1}" in
    start|stop|restart|status|config)
        fun_${arg1}
    ;;
    [vV][eE][rR][sS][iI][oO][nN]|-[vV][eE][rR][sS][iI][oO][nN]|--[vV][eE][rR][sS][iI][oO][nN]|-[vV]|--[vV])
        fun_version
    ;;
    [Cc]|[Cc][Oo][Nn][Ff]|[Cc][Oo][Nn][Ff][Ii][Gg]|-[Cc]|-[Cc][Oo][Nn][Ff]|-[Cc][Oo][Nn][Ff][Ii][Gg]|--[Cc]|--[Cc][Oo][Nn][Ff]|--[Cc][Oo][Nn][Ff][Ii][Gg])
        fun_config
    ;;
    [Hh]|[Hh][Ee][Ll][Pp]|-[Hh]|-[Hh][Ee][Ll][Pp]|--[Hh]|--[Hh][Ee][Ll][Pp])
        fun_help
    ;;
    *)
        fun_clangcn
        echo "Usage: $SCRIPTNAME {start|stop|restart|status|config|version}"
        RET_VAL=1
    ;;
esac
exit $RET_VAL

3、在目录/etc/rc3.d/ 下,新建一个指向在第2步中建立的服务文件的符号连接文件。

打开目录/etc/rc3.d/ ,我们将看到这里都是符号连接文件(linux系统中的符号连接相当于windows中的快捷方式)。采用以下命令格式:
ln -sf [目标文件名] [连接文件名]

举例,以安装 chfs 服务为例,输入以下代码:

cd /etc/rc3.d
ln -sf /chfs S10chfs

连接文件名称采用“SXX目标文件名”的格式,其中XX一般是一个从1到100的整数,它表示启动优先级,数字越大,优先级越低,比如:服务A的运行要依赖服务B,那A的XX数字就应该大于B的。后跟“目标文件名”是为了一目了然,一看就知道是哪个文件的符号连接。
目录/etc/rc3.d/ 是系统启动时自动搜索的目录,该目录下的符号连接文件的目标文件,都将被运行,这就是在这个目录建立符号连接的原因——为了开机就运行。

好了,完成以上3个步骤,你就把自己的一个可执行程序做成系统的一个服务了,它具有我们一开始说的几个特定。我们可以用service命令控制这个程序了:
启动:service chfs start
停止:service chfs stop
重启:service chfs restart
上面的chfs 为服务名,也就是在第2步中建立的文件名。

本文章由 brokenway 发布在 个人知识库 ,文章所述不代表本站观点,法律风险由发布者自行承担,转载请注明出处!