学校网站建设流程步骤,做网站需要什么人员,网站开发专业优势,四川哪家网站做的最好如何在Linux上设立一个软IOC框架
以下说明是基于我们的Debian Linux机器。其它发行版(或其他Unixes)会有不同命令和对于东西有不同位置。这对我添加到本页的Debian /etc/init.d尤其如此。如果你为一个不同发行版创建一个不同的脚本#xff0c;请添加它到本页。其它人将能够使…如何在Linux上设立一个软IOC框架
以下说明是基于我们的Debian Linux机器。其它发行版(或其他Unixes)会有不同命令和对于东西有不同位置。这对我添加到本页的Debian /etc/init.d尤其如此。如果你为一个不同发行版创建一个不同的脚本请添加它到本页。其它人将能够使用它。但基本步骤在所有发行版上相同。我已经认为了解了基本的系统管理任务(创建用户账户等)。 介绍
我们为什么做这件事
当在生产中使用软IOC时它们应该被当作重要的系统服务
软IOCs应该由系统启动和停止。应该有后备系统遇到硬件故障你可以简单地切换到这个后备系统。
其它目标是用如用于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
这个脚本的描述
DESCEPICS soft IOCs
这个脚本的完整路径
SCRIPTNAME/etc/init.d/softIOC获取主机名称
HOSTuname -n 设置procServ程序的路径
PROCSERV/usr/bin/procServ设置配置文件的完整路径
CONFFILE/usr/local/EPICS/program/softIOC/softiocs.orangepi5plus
设置IOC应用程序所在的家目录
HOMEDIRS/usr/local/EPICS/program
检查配置文件 不能读取配置文件显示不能找到配置文件并且以错误码1退出本脚本。
if [ ! -r $CONFFILE ]
thenecho Error: Cant 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 PORTdounset $option;done
}clear_options()的测试脚本如下
echo test clear_options()
export CA_AUTONO
export CA_ADDR127.0.0.1
export CA_PORT5065
export IOC_USERblctrl
export PORT20000
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_AUTONO
CA_ADDR127.0.0.1
CA_PORT5065
IOC_USERblctrl
PORT20000
call clear_options()
called clear_options()
CA_AUTO
CA_ADDR
CA_PORT
IOC_USER
PORT
end
根据读入参数设置环境变量
evaluate_options()
{while [ $# ! 0 ]do # 将第一个参数的小写字符全部替换成大写字母TAGecho $1 | tr [:lower:] [:upper:]case $TAG in#) ;; # 匹配”#”则进入下次循环CA_AUTO | CA_ADDR | CA_PORT | COREDUMPSIZE | \HOMEDIR | BOOTDIR | IOC_USER | PORT ) # 匹配这些字符# 测试当前选项值的存在OPTION$TAGshiftif [ -z $TAG -o $TAG # ] # TAG变量为空或者内容为”#”thenecho $CONFFILE: Value(s) required for $TAG.;exit 1elseVALUE$1shiftfi# 如果多个值跟随也分配它们while [ $1 ! # -a $# ! 0 ]doVALUE$VALUE $1shift;doneeval ${OPTION}\$VALUE;;*) echo $CONFFILE: Unknown option $1.exit 1esacshiftdone
}测试evaluate_options()函数的脚本
echo Test evaluate_options
ARGSCA_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_AUTONO
CA_ADDR127.0.0.1
CA_PORT5065 5066
IOC_USERblctrl
PORT20000
Test evaluate_options 为选项设置IOC环境变量默认值可能在配置文件中被重写
BOOTDIRIOC启动目录。HOMEDIRIOC应用程序顶层目录PIDFILE生产的pid文件路径ENVFILE环境文件路径IOC_USERIOC应用程序的用户
default_options()
{IOC_LC$1BOOTDIR$HOMEDIRS/$LOC_LC/iocBoot/ioc$LOC_LC/HOMEDIR$HOMEDIRS/$IOC_LCPIDFILE$HOMEDIR/$IOC_LC.pidENVFILE$HOMEDIR/$IOC_LC.envIOC_USERblctrl
}default_options()的测试脚本如下
#echo Test default_options()
default_options aiDriver
echo BOOTDIR$BOOTDIR
echo HOMEDIRS$HOMEDIRS
echo HOMEDIR$HOMEDIR
echo PIDFILE$PIDFILE
echo IOC_USERblctrl
#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_USERblctrl
从配置文件中读取配置信息并且生产一个如以下格式的
assign_options()
{TAG$1SECTIONsed -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: aiDriverGLOBAL: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 #
PORT20000
CA_AUTONO
CA_ADDR 192.168.50.10
CA_PORT 5080
IOC_USER blctrl从命令行或配置文件中AUTO:项获取IOCs。测试配置文件中的匹配段落。
get_iocs()
{if [ $# 0 ]thenTEST_LISTgrep -i ^AUTO: $CONFFILE | cut -d: -f2-elseTEST_LIST$fiCHECKED_LISTfor IOC in $TEST_LISTdogrep -qi ^$IOC: $CONFFILEif [ $? 0 ]thenCHECKED_LIST$CHECKED_LIST $IOCfidoneecho $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中并且进行导出SETENVLINES60 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\;PROCSERVOPTStest ! -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_cmdenvoptsecho SETENV$SETENV
echo PROCSERVOPTS$PROCSERVOPTSecho end
echo
测试结果如下
SETENV变量内容可以设置以下变量
LINES60export EPICS_CA_AUTO_ADDR_LISTNOexport EPICS_CA_ADDR_LIST127.0.0.1export EPICS_CA_SERVER_PORT5080;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()
SETENVLINES60 export EPICS_CA_AUTO_ADDR_LISTNO; export EPICS_CA_ADDR_LIST127.0.0.1; export EPICS_CA_SERVER_PORT5080; 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 ... MYIOCSget_iocs $[ $MYIOCS ] echo -n none for IOC in $MYIOCSdoecho -n $IOC clear_options #清除环境变量default_options $IOC #设置默认环境变量assign_options GLOBAL #设置全局设置的环境变量assign_options $IOC #设置本IOC的环境变量set_cmdenvopts #用于启动IOC的环境变量字符串用于procserv的选项字符串if [ -d $BOOTDIR ] # 测试启动目录是否存在thenif [ -d $HOMEDIR ] # 测试家目录是否存在then# 测试是否已经有pidfile文件$PIDFILE的进程在运行了如果是返回1sudo -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 ]thenecho -n was running else# 启动服务进程以及IOCsudo -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 ]thenecho -n failed fifielseecho -e \nWarning: Home directory $HOMEDIR does not exist! Ignoring $IOCfielseecho -e \nWarning: Boot directory $BOOTDIR does not exist! Ignoring $IOCfidoneecho ... done.
}
do_start的测试脚本如下
echo Test do_start()
default_options aiDriver
assign_options aiDriver
set_cmdenvoptsdo_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 Makefileftp本地连接20000端口进行测试
rootorangepi5plus:~# 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 restartprocServ server PID: 171785Server startup directory: /usr/local/EPICS/program/aiDriver/iocBoot/iocaiDriverChild startup directory: /usr/local/EPICS/program/aiDriver/iocBoot/iocaiDriver/Child orangepi started as: ./st.cmdChild orangepi PID: 171786procServ server started at: Fri Jul 5 15:11:02 2024Child orangepi started at: Fri Jul 5 15:11:02 20240 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 --retryTERM/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 ... MYIOCSget_iocs $[ $MYIOCS ] echo -n none for IOC in $MYIOCSdoecho -n $IOC clear_optionsdefault_options $IOCassign_options GLOBALassign_options $IOCset_cmdenvopts# 测试停止守护进程, 返回1表示已经停止sudo -H -u $IOC_USER bash -c /usr/sbin/start-stop-daemon --stop --quiet --pidfile $PIDFILE --name procServ --test /dev/nullif [ $? 1 ]thenecho -n not running elsesudo -H -u $IOC_USER bash -c /usr/sbin/start-stop-daemon --stop --quiet --retryTERM/30/KILL/5 --pidfile $PIDFILE --name procServif [ $? 1 ]thenecho -n failed elsesudo -H -u $IOC_USER bash -c rm -f $PIDFILEfifidoneecho ... done.
}
do_stop的测试脚本
echo Test do_start()
default_options aiDriver
assign_options aiDriver
set_cmdenvoptsdo_stop aiDriver
echo end
echo
测试结果如下ftp服务程序和epics ioc程序都已经终止。
Test do_start()
Stopping soft IOCs ... aiDriver ... done.
endrootorangepi5plus:~# 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,pid1383,fd3))
LISTEN 0 4 127.0.0.1:5037 0.0.0.0:* users:((adbd,pid849,fd5))
LISTEN 0 4096 0.0.0.0:111 0.0.0.0:* users:((rpcbind,pid900,fd4),(systemd,pid1,fd32))
LISTEN 0 4 0.0.0.0:5555 0.0.0.0:* users:((adbd,pid849,fd10))
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:((systemd-resolve,pid901,fd14))
LISTEN 0 128 [::]:22 [::]:* users:((sshd,pid1383,fd4))
LISTEN 0 4096 [::]:111 [::]:* users:((rpcbind,pid900,fd6),(systemd,pid1,fd34))
并且IOC顶层目录中pidfile文件也被删除了
rootorangepi5plus:/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 0echo Restarting soft IOCs ... STARTDIR$PWDIOCSget_iocs $[ $IOCS ] echo -n none for IOC in $IOCSdoecho -n $IOC clear_optionsdefault_options $IOCassign_options GLOBALassign_options $IOCif [ -d $BOOTDIR ]thencd $BOOTDIR
# restart it!echo -e \ndebug: Reloading ioc $IOCcd $STARTDIRelseecho -e \nWarning: Boot directory $BOOTDIR does not exist! Entry for $NET ignored!fidoneecho ... done.
}
以下脚本用于从命令 行获取参数并且执行守护进程启动/停止/重启
COMMAND$1
shift
IOCSecho $case $COMMAND instart)do_start $IOCS;;stop)do_stop $IOCS;;restart|force-reload)do_stop $IOCSsleep 1do_start $IOCS;;*)echo Usage: $SCRIPTNAME {start|stop|restart|force-reload} [iocs ...] 2exit 3;;
esac
以下命令行启动IOC
rootorangepi5plus:~# ./test.sh start aiDriver
Starting soft IOCs ... aiDriver ... done.
rootorangepi5plus:~# 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,pid1383,fd3))
LISTEN 0 20 0.0.0.0:5080 0.0.0.0:* users:((st.cmd,pid172122,fd13))
LISTEN 0 5 127.0.0.1:20000 0.0.0.0:* users:((st.cmd,pid172122,fd3),(procServ,pid172121,fd3))
LISTEN 0 4 127.0.0.1:5037 0.0.0.0:* users:((adbd,pid849,fd5))
LISTEN 0 4096 0.0.0.0:111 0.0.0.0:* users:((rpcbind,pid900,fd4),(systemd,pid1,fd32))
LISTEN 0 4 0.0.0.0:5075 0.0.0.0:* users:((st.cmd,pid172122,fd15))
LISTEN 0 4 0.0.0.0:5555 0.0.0.0:* users:((adbd,pid849,fd10))
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:((systemd-resolve,pid901,fd14))
LISTEN 0 128 [::]:22 [::]:* users:((sshd,pid1383,fd4))
LISTEN 0 4096 [::]:111 [::]:* users:((rpcbind,pid900,fd6),(systemd,pid1,fd34))以下命令行停止IOCjj
rootorangepi5plus:~# ./test.sh stop aiDriver
Stopping soft IOCs ... aiDriver ... done.
rootorangepi5plus:~# 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,pid1383,fd3))
LISTEN 0 4 127.0.0.1:5037 0.0.0.0:* users:((adbd,pid849,fd5))
LISTEN 0 4096 0.0.0.0:111 0.0.0.0:* users:((rpcbind,pid900,fd4),(systemd,pid1,fd32))
LISTEN 0 4 0.0.0.0:5555 0.0.0.0:* users:((adbd,pid849,fd10))
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:((systemd-resolve,pid901,fd14))
LISTEN 0 128 [::]:22 [::]:* users:((sshd,pid1383,fd4))
LISTEN 0 4096 [::]:111 [::]:* users:((rpcbind,pid900,fd6),(systemd,pid1,fd34))
将以下test.sh更名为softIOC并复制到/etc/init.d/目录下IOC应用程序就可以当作系统服务程序一样被启动。
rootorangepi5plus:~# /etc/init.d/softIOC start aiDriver
Starting soft IOCs ... aiDriver ... done.
rootorangepi5plus:~# /etc/init.d/softIOC stop aiDriver
Stopping soft IOCs ... aiDriver ... done.