Ubuntu 22.04上/etc/init.d/softIOC脚本解析

如何在Linux上设立一个软IOC框架

以下说明是基于我们的Debian Linux机器。其它发行版(或其他Unixes)会有不同命令和对于东西有不同位置。这对我添加到本页的Debian /etc/init.d尤其如此。如果你为一个不同发行版创建一个不同的脚本,请添加它到本页。其它人将能够使用它。但基本步骤在所有发行版上相同。我已经认为了解了基本的系统管理任务(创建用户账户等)。

介绍

我们为什么做这件事?

当在生产中使用软IOC时,它们应该被当作重要的系统服务:

  1. 软IOCs应该由系统启动和停止。
  2. 应该有后备系统,遇到硬件故障,你可以简单地切换到这个后备系统。

其它目标是:用如用于VME IOCs相同地方法,应用程序开发这应该能够在无需对主机进行root访问下重置软IOC。

  • IOC应用开发者应该能够手动启动和停止IOCs。

当多个软IOC共享相同主机(和相同IP地址)时,通道访问不能区分它们。访问安全将不能区分来自不同软IOCs的CA连接。在调试客户端时,CA不能告诉你一个连接去向哪个软IOCs。

  • 即使不同软IOCs驻留在相同机器上,通道访问应该能够区分不同的软IOCs。

我曾考虑使用一个虚拟化层(基于VMware)在一个封装环境中运行软IOCs。我发现工作量太高,此层太厚,并且预计的性能损失太大--仅得到了每个软IOIC一个单独IP地址。

在调试和/或尝试查看在一个IOC上发生了什么时,开发者不必要知道数据库运行在一个基于VME上还是在一个基于主机的软IOC上。

  • Console访问(以及记录console输出日志)应该是统一的:对于软IOCs和VME IOCs使用相同方式。

实现这个目标所需的设置在文档<<如何为VME和软IOCs设置Console访问和日志>>。

概念

要使访问安全区分软IOCs,在不同用户名下运行它们。

procServ工具将用做一个环境,它允许在后台启动软IOCs并且之后连接到它们的consoles,非常类型VME IOCs的串行consoles。(见EPICS Related Software — EPICS Documentation documentation (epics-controls.org)上procServ链接。之前,使用screen工具,但报告的问题,例如,在console访问后IOCs挂起,使得我们切花到复杂性更低的东西)。

/etc/init.d/softIOC是用于将EPICS软IOC作为系统服务启动的脚本:参考网页https://wiki-ext.aps.anl.gov/epics/index.php/How_to_Set_Up_a_Soft_IOC_Framework_on_Linux

这个脚本的描述:

DESC="EPICS soft IOCs"

这个脚本的完整路径:

SCRIPTNAME=/etc/init.d/softIOC

获取主机名称:

HOST=`uname -n`

 设置procServ程序的路径

PROCSERV=/usr/bin/procServ

设置配置文件的完整路径: 

CONFFILE=/usr/local/EPICS/program/softIOC/softiocs.orangepi5plus

设置IOC应用程序所在的家目录: 

HOMEDIRS=/usr/local/EPICS/program

检查配置文件 , 不能读取配置文件,显示不能找到配置文件,并且以错误码1退出本脚本。

if [ ! -r $CONFFILE ]
then
        echo "Error: Can't find configuration file $CONFFILE!"
        exit 1
fi

 此函数函数:清理环境变量"CA_AUTO" "CA_ADDR" "CA_PORT" "IOC_USER" "PORT"。

clear_options()
{
        for option in "CA_AUTO" "CA_ADDR" "CA_PORT" "IOC_USER" "PORT"
        do
                unset $option;
        done
}

clear_options()的测试脚本如下:

echo "=============test clear_options() ====================="
export CA_AUTO="NO"
export CA_ADDR="127.0.0.1"
export CA_PORT=5065
export IOC_USER="blctrl"
export PORT="20000"
echo "CA_AUTO=$CA_AUTO"
echo "CA_ADDR=$CA_ADDR"
echo "CA_PORT=$CA_PORT"
echo "IOC_USER=$IOC_USER"
echo "PORT=$PORT"
echo "call clear_options()"
clear_options
echo "called clear_options()"
echo "CA_AUTO=$CA_AUTO"
echo "CA_ADDR=$CA_ADDR"
echo "CA_PORT=$CA_PORT"
echo "IOC_USER=$IOC_USER"
echo "PORT=$PORT"
echo "===================end================================="
echo ""

测试结果:

=============test clear_options() =====================
CA_AUTO=NO
CA_ADDR=127.0.0.1
CA_PORT=5065
IOC_USER=blctrl
PORT=20000
call clear_options()
called clear_options()
CA_AUTO=
CA_ADDR=
CA_PORT=
IOC_USER=
PORT=
===================end=================================

根据读入参数设置环境变量:

evaluate_options()
{
        while [ $# != 0 ]
        do      # 将第一个参数的小写字符全部替换成大写字母
                TAG=`echo $1 | tr [:lower:] [:upper:]`
                case "$TAG" in
                "#")            ;; # 匹配”#”,则进入下次循环
                "CA_AUTO" | "CA_ADDR" | "CA_PORT" | "COREDUMPSIZE" | \
                "HOMEDIR" | "BOOTDIR" | "IOC_USER" | "PORT" ) # 匹配这些字符
                                # 测试当前选项值的存在
                                OPTION=$TAG
                                shift
                                if [ -z $TAG -o $TAG = "#" ] # TAG变量为空或者内容为”#”
                                then
                                        echo "$CONFFILE: Value(s) required for $TAG.";
                                        exit 1
                                else
                                        VALUE=$1
                                        shift
                                fi
                                # 如果多个值跟随,也分配它们
                                while [ $1 != '#'  -a  $# != 0 ]
                                do
                                        VALUE="$VALUE $1"
                                        shift;
                                done
                                eval ${OPTION}=\$VALUE
                                ;;
                *)              echo "$CONFFILE: Unknown option $1."
                                exit 1
                esac
                shift
        done
}

测试evaluate_options()函数的脚本:

echo "============================Test evaluate_options============================="
ARGS="CA_AUTO NO # CA_ADDR 127.0.0.1 # CA_PORT 5065 5066 # IOC_USER blctrl # PORT 20000"
evaluate_options ${ARGS}
echo CA_AUTO=$CA_AUTO
echo CA_ADDR=$CA_ADDR
echo CA_PORT=$CA_PORT
echo IOC_USER=$IOC_USER
echo PORT=$PORT
echo "============================Test evaluate_options==============================="

测试结果如下:

============================Test evaluate_options=============================
CA_AUTO=NO
CA_ADDR=127.0.0.1
CA_PORT=5065 5066
IOC_USER=blctrl
PORT=20000
============================Test evaluate_options===============================

  为选项设置IOC环境变量默认值可能在配置文件中被重写:

  • BOOTDIR:IOC启动目录。
  • HOMEDIR:IOC应用程序顶层目录
  • PIDFILE:生产的pid文件路径
  • ENVFILE:环境文件路径
  • IOC_USER:IOC应用程序的用户
default_options()
{
        IOC_LC=$1
     
        BOOTDIR=$HOMEDIRS/$LOC_LC/iocBoot/ioc$LOC_LC/
        HOMEDIR=$HOMEDIRS/$IOC_LC
        PIDFILE=$HOMEDIR/$IOC_LC.pid
        ENVFILE=$HOMEDIR/$IOC_LC.env
        IOC_USER=blctrl
}

default_options()的测试脚本如下:

#echo "===================Test default_options()=============="
default_options "aiDriver"
echo "BOOTDIR=$BOOTDIR"
echo "HOMEDIRS=$HOMEDIRS"
echo "HOMEDIR=$HOMEDIR"
echo "PIDFILE=$PIDFILE"
echo "IOC_USER=blctrl"
#echo "===================end================================="
#echo ""

测试结果如下:

BOOTDIR=/usr/local/EPICS/program/aiDriver/iocBoot/iocaiDriver/
HOMEDIRS=/usr/local/EPICS/program
HOMEDIR=/usr/local/EPICS/program/aiDriver
PIDFILE=/usr/local/EPICS/program/aiDriver/aiDriver.pid
IOC_USER=blctrl

从配置文件中读取配置信息,并且生产一个如以下格式的 

assign_options()
{
        TAG=$1
        SECTION=`sed -n "/^$TAG:/I,/^[\t ]*$/p" $CONFFILE | \      # 查找$TAG段落
                 sed -n '/^[^#]/p' | \                             # 删除注释 
                 sed -e 's/^[ \t]*//' -e 's/[ \t]*$//' \           # 删除开头和结尾空白
                     -e "s/$TAG://I" \                             # 移除$TAG:标签
                     -e :a -e '/\\\\$/N; s/\\\\\\n//; ta' \        # 将以一个”\”结尾的行合并
                     -e 's/$/ \#/' \                               # 用一个”#”标记选项结尾
                     -e 's/[\t ]/ /g'`                             #移除不必要的空白
        evaluate_options $SECTION
}

assign_options的测试脚本如下:

echo "=================Test assign_options()================="
assign_options aiDriver
echo SECTION=$SECTION
echo PORT=$PORT
echo CA_AUTO=$CA_AUTO
echo CA_ADDR =$CA_ADDR
echo CA_PORT =$CA_PORT
echo IOC_USER =$IOC_USER
echo "===================end================================="
echo ""

配置文件所在完整路径/usr/local/EPICS/program/softIOC/softiocs.orangepi5plus:

AUTO:   aiDriver

GLOBAL:

aiDriver:
# 配置端口号
PORT 20000
CA_AUTO NO
CA_ADDR 192.168.50.10
CA_PORT 5080
IOC_USER blctrl
PORT 20000

测试结果如下:

=================Test assign_options()=================
SECTION= # PORT 20000 # CA_AUTO NO # CA_ADDR 192.168.50.10 # CA_PORT 5080 # IOC_USER blctrl # PORT 20000 #
PORT=20000
CA_AUTO=NO
CA_ADDR =192.168.50.10
CA_PORT =5080
IOC_USER =blctrl

从命令行或配置文件中AUTO:项获取IOCs。测试配置文件中的匹配段落。

get_iocs()
{
        if [ $# = 0 ]
        then
                TEST_LIST=`grep -i '^AUTO:' "$CONFFILE" | cut -d: -f2-`
        else
                TEST_LIST="$@"
        fi

        CHECKED_LIST=""
        for IOC in $TEST_LIST
        do
                grep -qi "^$IOC:" $CONFFILE
                if [ $? = 0 ]
                then
                        CHECKED_LIST="$CHECKED_LIST $IOC"
                fi
        done
        echo $CHECKED_LIST
}

get_iocs()的测试脚本如下: 

echo "===============Test get_iocs()========================="
echo "call get_iocs"
get_iocs
echo "call get_iocs aiDriver"
get_iocs aiDriver
echo "===================end================================="
echo ""

测试结果如下:

===============Test get_iocs()=========================
call get_iocs
aiDriver
call get_iocs aiDriver
aiDriver
===================end=================================

 此脚本第一方面设置环境变量设置字符串,例如CA_AUTO环变量不为空,则将其设置到环境变量,其它CA_XXX环境变量的设置类似,第二方面为procserv程序设置选项。

set_cmdenvopts()
{
       EPICS_CA_AUTO_ADDR_LIST中,并且进行导出
        SETENV="LINES=60 "`test ! -z "$CA_AUTO" && echo "export EPICS_CA_AUTO_ADDR_LIST=\"$CA_AUTO\";"`
        SETENV="$SETENV "`test ! -z "$CA_ADDR" && echo "export EPICS_CA_ADDR_LIST=\"$CA_ADDR\";"`
        SETENV="$SETENV "`test ! -z "$CA_PORT" && echo "export EPICS_CA_SERVER_PORT=\"$CA_PORT\";"`
        SETENV="$SETENV "`test ! -z "$BOOTDIR" && echo "export BOOTDIR=\"$BOOTDIR\";"`

        PROCSERVOPTS=`test ! -z "$IOC_USER" && echo "-n \"$IOC_USER\""`
        PROCSERVOPTS="$PROCSERVOPTS "`test ! -z "$COREDUMPSIZE" && echo "--coresize \"$COREDUMPSIZE\""`
        PROCSERVOPTS="$PROCSERVOPTS -q -c $BOOTDIR -p $PIDFILE -i ^D^C^] $PORT"
}

set_cmdenvpots()的测试脚本如下:

echo "================Test set_cmdenvopts()=================="
default_options aiDriver
assign_options aiDriver
set_cmdenvopts

echo "SETENV=$SETENV"
echo "PROCSERVOPTS=$PROCSERVOPTS"

echo "===================end================================="
echo ""

测试结果如下:

SETENV变量内容可以设置以下变量:

  • LINES=60
  • export EPICS_CA_AUTO_ADDR_LIST="NO"
  • export EPICS_CA_ADDR_LIST="127.0.0.1"
  • export EPICS_CA_SERVER_PORT="5080";
  • export BOOTDIR="/usr/local/EPICS/program/aiDriver/iocBoot/iocaiDriver/"

PROCSERVPORTS内容可以设置procserv的选项:

  • -n "blctrl"  :在所有服务程序消息中,使用blctrl替代完整命令行来增加可读性。
  • -q:不要写信息输出(服务程序)。当作为系统脚本的一部分运行时,避免弄乱屏幕。
  • -c /usr/local/EPICS/program/aiDriver/iocBoot/iocaiDriver/:在启动子进程前,切换目录为 /usr/local/EPICS/program/aiDriver/iocBoot/iocaiDriver/。
  • -p /usr/local/EPICS/program/aiDriver/aiDriver.pid:写服务进程的PID到file以便于集成到常规的系统服务管理机制中。
  • -i ^D^C^]:忽略访问连接上再chars中所有字符。
  • 20000:本地ftp连接端口。
================Test set_cmdenvopts()==================
SETENV=LINES=60 export EPICS_CA_AUTO_ADDR_LIST="NO"; export EPICS_CA_ADDR_LIST="127.0.0.1"; export EPICS_CA_SERVER_PORT="5080"; export BOOTDIR="/usr/local/EPICS/program/aiDriver/iocBoot/iocaiDriver/";
PROCSERVOPTS=-n "blctrl"  -q -c /usr/local/EPICS/program/aiDriver/iocBoot/iocaiDriver/ -p /usr/local/EPICS/program/aiDriver/aiDriver.pid -i ^D^C^] 20000
===================end=================================

启动守护/服务进程的函数: 

do_start()
{
        # 返回
        #   0:启动了守护进程 
        #   1:守护进程已经在运行 
        #   2:不能启动守护进程 
        # 如果需要,在此处添加代码,其等待这个进程准备好处理来自之后启动的服务的请求,这个服务依赖于这个进程。作为最后的方法,休眠一段时间。
        echo -n "Starting soft IOCs ... "
        MYIOCS=`get_iocs $@`
        [ "$MYIOCS" = "" ] && echo -n "<none> "
        for IOC in $MYIOCS
        do
                echo -n "$IOC "
                clear_options           #清除环境变量
                default_options "$IOC"  #设置默认环境变量
                assign_options "GLOBAL" #设置全局设置的环境变量
                assign_options "$IOC"   #设置本IOC的环境变量
                set_cmdenvopts          #用于启动IOC的环境变量字符串,用于procserv的选项字符串

                if [ -d $BOOTDIR ]     # 测试启动目录是否存在
                    then
                    if [ -d $HOMEDIR ] # 测试家目录是否存在
                        then
                        # 测试是否已经有pidfile文件$PIDFILE的进程在运行了,如果是返回1
                        sudo -H -u $IOC_USER bash -c "$SETENV (env > $ENVFILE; /usr/sbin/start-stop-daemon --start --quiet --chdir $BOOTDIR \
                            --pidfile $PIDFILE --startas $PROCSERV --name procServ --test > /dev/null)"
                        if [ "$?" = 1 ]
                            then
                            echo -n "<was running> "
                            else
                            # 启动服务进程以及IOC
                            sudo -H -u $IOC_USER bash -c "$SETENV (env > $ENVFILE; /usr/sbin/start-stop-daemon --start --quiet --chdir $BOOTDIR \
                                --pidfile $PIDFILE --startas $PROCSERV --name procServ -- $PROCSERVOPTS ./st.cmd)"
                            if [ "$?" = 1 ]
                                then
                                echo -n "<failed> "
                            fi
                        fi

                    else
                        echo -e "\nWarning: Home directory $HOMEDIR does not exist! Ignoring $IOC"
                    fi
                else
                        echo -e "\nWarning: Boot directory $BOOTDIR does not exist! Ignoring $IOC"
                fi
        done
        echo "... done."
}

do_start的测试脚本如下:

echo "========================Test do_start()============================="
default_options aiDriver
assign_options aiDriver
set_cmdenvopts

do_start aiDriver
echo "===================end================================="
echo ""

测试结果如下:

========================Test do_start()=============================
Starting soft IOCs ... aiDriver ... done.
===================end=================================

IOC顶层目录下,产生两个新的文件aiDriver.env和aiDriver.pid:

:/usr/local/EPICS/program/aiDriver# ls
aiDriverApp  aiDriver.env  aiDriver.pid  bin  configure  db  dbd  iocBoot  lib  Makefile

ftp本地连接20000端口,进行测试:

root@orangepi5plus:~# telnet localhost 20000
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
@@@ Welcome to procServ (procServ Process Server 2.7.0)
@@@ Use ^X to kill the child, auto restart is ON, use ^T to toggle auto restart
@@@ procServ server PID: 171785
@@@ Server startup directory: /usr/local/EPICS/program/aiDriver/iocBoot/iocaiDriver
@@@ Child startup directory: /usr/local/EPICS/program/aiDriver/iocBoot/iocaiDriver/
@@@ Child "orangepi" started as: ./st.cmd
@@@ Child "orangepi" PID: 171786
@@@ procServ server started at: Fri Jul  5 15:11:02 2024
@@@ Child "orangepi" started at: Fri Jul  5 15:11:02 2024
@@@ 0 user(s) and 0 logger(s) connected (plus you)

epics> dbl
Random:AiRandom

通道访问这个IOC:

caget Random:AiRandom
Random:AiRandom                527

停止守护/服务进程的函数:

sudo -H -u $IOC_USER bash -c "/usr/sbin/start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name procServ"

--retry:使用--stop,指定start-stop-daemon检查这些进程是否结束了。它将重复检查任何匹配的进行是否正在运行,直到没有匹配的进程运行。如果这些进程不存在,它将采取由调度表决定的进一步操作。如果指定了timeout替代schedule,则调度表signal/timeout/KILL/timeout被使用,此处signal是由--signal指定的信号。

schedule是一个列表,其至少有由斜杆(/)分隔的两项;每项可能是-signal-number或[-]signal-name,它表示发送那个信号,或timeout,它表示为进程退出等待那些秒数,或者forever,它表示如果需要一直重复调度表余下的。

do_stop()
{
        # 返回:
        #   0:守护进程被停止
        #   1:守护进程已经停止
        #   2:守护进程不能被停止
        #   3:发生故障
        echo -n "Stopping soft IOCs ... "
        MYIOCS=`get_iocs $@`
        [ "$MYIOCS" = "" ] && echo -n "<none> "
        for IOC in $MYIOCS
        do
                echo -n "$IOC "
                clear_options
                default_options "$IOC"
                assign_options "GLOBAL"
                assign_options "$IOC"
                set_cmdenvopts
                # 测试停止守护进程, 返回1,表示已经停止
                sudo -H -u $IOC_USER bash -c "/usr/sbin/start-stop-daemon --stop --quiet --pidfile $PIDFILE --name procServ --test > /dev/null"
                if [ $? = 1 ]
                    then
                    echo -n "<not running> "
                    else
                    sudo -H -u $IOC_USER bash -c "/usr/sbin/start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name procServ"
                    if [ $? = 1 ]
                        then
                        echo -n "<failed> "
                    else
                        sudo -H -u $IOC_USER bash -c "rm -f $PIDFILE"
                    fi
                fi
        done
        echo "... done."
}

do_stop的测试脚本:

echo "========================Test do_start()============================="
default_options aiDriver
assign_options aiDriver
set_cmdenvopts

do_stop aiDriver
echo "===================end================================="
echo ""

测试结果如下,ftp服务程序和epics ioc程序都已经终止。

========================Test do_start()=============================
Stopping soft IOCs ... aiDriver ... done.
===================end=================================

root@orangepi5plus:~# ss -tlnp
State      Recv-Q     Send-Q          Local Address:Port           Peer Address:Port     Process
LISTEN     0          128                   0.0.0.0:22                  0.0.0.0:*         users:(("sshd",pid=1383,fd=3))
LISTEN     0          4                   127.0.0.1:5037                0.0.0.0:*         users:(("adbd",pid=849,fd=5))
LISTEN     0          4096                  0.0.0.0:111                 0.0.0.0:*         users:(("rpcbind",pid=900,fd=4),("systemd",pid=1,fd=32))
LISTEN     0          4                     0.0.0.0:5555                0.0.0.0:*         users:(("adbd",pid=849,fd=10))
LISTEN     0          4096            127.0.0.53%lo:53                  0.0.0.0:*         users:(("systemd-resolve",pid=901,fd=14))
LISTEN     0          128                      [::]:22                     [::]:*         users:(("sshd",pid=1383,fd=4))
LISTEN     0          4096                     [::]:111                    [::]:*         users:(("rpcbind",pid=900,fd=6),("systemd",pid=1,fd=34))

并且IOC顶层目录中pidfile文件也被删除了:

root@orangepi5plus:/usr/local/EPICS/program/aiDriver# ls
aiDriverApp  aiDriver.env  bin  configure  db  dbd  iocBoot  lib  Makefile

发送SIGHUP信号给守护/服务进程的函数如下(此处没有实现):

do_reload() {
        # 如果守护进程可以在不重启下重载其配置(例如,当向其发送要给SIGHUP),
        # 则在此实现。
     
#       start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
#       return 0

        echo "Restarting soft IOCs ... "
        STARTDIR=$PWD
        IOCS=`get_iocs $@`
        [ "$IOCS" = "" ] && echo -n "<none> "
        for IOC in $IOCS
        do
                echo -n "$IOC "
                clear_options
                default_options "$IOC"
                assign_options "GLOBAL"
                assign_options "$IOC"
                if [ -d $BOOTDIR ]
                then
                        cd "$BOOTDIR"
# restart it!
                        echo -e "\ndebug: Reloading ioc $IOC"
                        cd "$STARTDIR"
                else
                        echo -e "\nWarning: Boot directory $BOOTDIR does not exist! Entry for $NET ignored!"
                fi
        done
        echo "... done."
}

以下脚本用于从命令 行获取参数,并且执行守护进程启动/停止/重启:

COMMAND=$1
shift
IOCS=`echo $@`

case "$COMMAND" in
  start)
        do_start $IOCS
        ;;
  stop)
        do_stop $IOCS
        ;;
  restart|force-reload)
        do_stop $IOCS
        sleep 1
        do_start $IOCS
        ;;
  *)
        echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload} [iocs ...]" >&2
        exit 3
        ;;
esac

以下命令行启动IOC:

root@orangepi5plus:~# ./test.sh start aiDriver
Starting soft IOCs ... aiDriver ... done.
root@orangepi5plus:~# ss -lntp
State     Recv-Q    Send-Q        Local Address:Port          Peer Address:Port    Process
LISTEN    0         128                 0.0.0.0:22                 0.0.0.0:*        users:(("sshd",pid=1383,fd=3))
LISTEN    0         20                  0.0.0.0:5080               0.0.0.0:*        users:(("st.cmd",pid=172122,fd=13))
LISTEN    0         5                 127.0.0.1:20000              0.0.0.0:*        users:(("st.cmd",pid=172122,fd=3),("procServ",pid=172121,fd=3))
LISTEN    0         4                 127.0.0.1:5037               0.0.0.0:*        users:(("adbd",pid=849,fd=5))
LISTEN    0         4096                0.0.0.0:111                0.0.0.0:*        users:(("rpcbind",pid=900,fd=4),("systemd",pid=1,fd=32))
LISTEN    0         4                   0.0.0.0:5075               0.0.0.0:*        users:(("st.cmd",pid=172122,fd=15))
LISTEN    0         4                   0.0.0.0:5555               0.0.0.0:*        users:(("adbd",pid=849,fd=10))
LISTEN    0         4096          127.0.0.53%lo:53                 0.0.0.0:*        users:(("systemd-resolve",pid=901,fd=14))
LISTEN    0         128                    [::]:22                    [::]:*        users:(("sshd",pid=1383,fd=4))
LISTEN    0         4096                   [::]:111                   [::]:*        users:(("rpcbind",pid=900,fd=6),("systemd",pid=1,fd=34))

以下命令行停止IOC:jj

root@orangepi5plus:~# ./test.sh stop aiDriver
Stopping soft IOCs ... aiDriver ... done.
root@orangepi5plus:~# ss -lntp
State      Recv-Q     Send-Q          Local Address:Port           Peer Address:Port     Process
LISTEN     0          128                   0.0.0.0:22                  0.0.0.0:*         users:(("sshd",pid=1383,fd=3))
LISTEN     0          4                   127.0.0.1:5037                0.0.0.0:*         users:(("adbd",pid=849,fd=5))
LISTEN     0          4096                  0.0.0.0:111                 0.0.0.0:*         users:(("rpcbind",pid=900,fd=4),("systemd",pid=1,fd=32))
LISTEN     0          4                     0.0.0.0:5555                0.0.0.0:*         users:(("adbd",pid=849,fd=10))
LISTEN     0          4096            127.0.0.53%lo:53                  0.0.0.0:*         users:(("systemd-resolve",pid=901,fd=14))
LISTEN     0          128                      [::]:22                     [::]:*         users:(("sshd",pid=1383,fd=4))
LISTEN     0          4096                     [::]:111                    [::]:*         users:(("rpcbind",pid=900,fd=6),("systemd",pid=1,fd=34))

将以下test.sh更名为softIOC并复制到/etc/init.d/目录下,IOC应用程序就可以当作系统服务程序一样被启动。

root@orangepi5plus:~# /etc/init.d/softIOC start aiDriver
Starting soft IOCs ... aiDriver ... done.
root@orangepi5plus:~# /etc/init.d/softIOC stop aiDriver
Stopping soft IOCs ... aiDriver ... done.
  • 13
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值