Linux Shell在卫星定轨软件中的应用
2014-08-22马宏阳张龙平
马宏阳,张龙平
(1.中国测绘科学研究院,北京 100830;2.山东科技大学,山东 青岛 266510)
0 引 言
Linux是一套可免费使用和自由传播的类UNIX操作系统,经过近20年来的发展,Linux成为了一个支持多用户、多进程、多线程,实时性较好、功能强大而稳定的操作系统,它也是目前支持硬件平台最多的操作系统[1-3]。除了桌面领域,Linux在其他领域都取得了巨大的进步和成功。其开放、安全、稳定的特性得到越来越多用户的认可,许多导航定位领域广泛应用的软件都是基于Linux开发[4],如GAMIT/GlobK、GIPS、Bernese、PANDA等。许多IGS分析中心也将Linux作为平台操作系统。Linux自诞生以来发布了许多不同的版本,常见的有Slackware、RedHat、Debian、Fedora、S.u.s.E.等。本文的实验环境选择了S.u.s.E. 11,它是2008年发布的S.u.s.E.版本,是一个开放的、创新的、具有前瞻性的免费Linux系统。
Shell是一种具备特殊功能的程序,它提供了用户与内核进行交互操作的一种接口,它接受用户输入的命令,并把它送入内核去执行[5-6]。内核是Linux系统的心脏,当用户登录Linux系统时,Shell就会被调入内存执行。Shell独立于内核,它是连接内核和应用程序的桥梁,并由输入设备读取命令,再将其转为计算机可以理解的机械码,Linux才能执行该命令。本文根据实际工作经验,详细介绍了C Shell语言在Linux系统下辅助卫星定轨软件起到的作用。
1 数据下载
数据解算的第一步是下载所需的数据,如观测文件、广播星历和频间偏差等文件,对于卫星定轨而言,需要下载几十甚至上百个观测站的数据,如果手动下载会非常繁琐,本节介绍两个常用的数据下载命令。
1.1 wget命令
以下载MGEX观测站的多模观测文件的小时文件为例,其命令为
set pth=/cddis.gsfc.nasa.gov/pub/gnss/data
set site-list=site-list-mgex
set chour=(a b c d e f g h i j k l m n o p q r s t u v w x)
set ihour=$hour+1
foreach s (`cat $site-list`)
wget ftp://$pth/hourly/$yyyy/$doy/$hour/$s$doy$chour[$ihour].$yy"o.Z"
end
其中,$pth为MGEX数据下载路径;$yyyy、$doy、$hour分别为年、年积日、小时,均可以作为变量输入;$site-list为需要下载的站列表文件;$yy 为两位数的年;foreach为循环站列表文件,并将站名赋给$s;$s$doy$chour[$ihour].$yy"o.Z"即为需要下载的某个测站小时观测文件名称,全部使用变量表示,因此利用该脚本,可以下载任意时段的指定站列表小时数据。
该网站的数据可以免费下载,若下载数据的ftp地址设置了用户名和密码,可以将命令改写为
wget-ftp-user=user_name-ftp-password
=secret
值得注意的是,wget会不断的尝试下载没有下载成功的数据,因此有必要介绍两个常用的参数,-t为设置下载尝试次数,-w为设置下载最大时长,均可以避免在一个站上消耗大量时间。
一般IGS站的小时观测文件延迟半小时之内上传,而MGEX站会延迟更长时间,因此有可能出现在下载时刻数据还没有上传的情况,因此最好是下载完成一个小时的数据后,再补下前一个小时的数据,命令为
while (0 < 1)
@ hour=$hour-1
if($hour < 0)then
@doy=$doy-1
if($doy==0)then
@yyyy=$yyyy-1
@doy=`dpy $yyyy`
endif
@ hour=23
endif
set hour=`echo $hour | awk '{printf("%2.2d",$1)}'`
set doy=`echo $doy | awk '{printf("%3.3d",$1)}'`
……
end
该脚本实现将时间调至前一个小时,while (0 < 1)给出一个死循环,只要不结束该脚本,它就会一直循环补充下载前一个小时的观测文件;若是出现跨天的情况,则年积日减1,$hour变为23,若是出现跨年的情况,则年减1,年积日为该年的最后一天,@ doy=`dpy $yyyy`为调用“dyp”命令,计算该年有多少天;awk '{printf("%2.2d",$1)}为将$hour写成两位数的小时,同样,$doy也写成三位数的年积日,这是为了和下载目录向对应。
既然给出了while (0 < 1)的死循环,肯定有一个时刻要将该脚本关闭。可以首先使用“ps-ef”查看该脚本运行的ID,再使用“kill-9 %ID”强制关闭脚本的进程。使用这种方法每次都需要人工查看脚本ID,不适合自动化运行,因此可以使用如下结束进程的脚本:
set name="get_hourly"
set id=`ps-ef | grep "$name" | grep-v"$0" | grep-v"grep" | awk’{print $2}’
kill-9 $id
这样,仅给出需要结束的进程名称(get_hourly),脚本就可以自动获取其进程ID,结束该进程。
1.2 mget命令
该命令与wget命令的区别是,wget每下载一个数据都要登入和登出一次,而mget登入后,会将所需文件全部下载完毕才登出,从理论上讲,mget会比wget的效率更高。由于使用mget命令需要登录对方服务器,因此必须设置用户名和密码,其命令为
if(!-d./$yyyy)then
mkdir $yyyy
cd./$yyyy/
mkdir $doy
cd $pth-pwd
endif
set file-name=""
foreach s (`cat $site-list`)
set file-name=($file-name $s$doy$chour[$ihour].$yy"o.Z")
end
set HOST="cddis.gsfc.nasa.gov"
set USER="anonymous"
set PASS='^M'
ftp -inv $HOST ≪EOF
user $USER $PASS
cd/gnss/data/campaign/mgex/hourly/rinex3/$yyyy/$doy/$hour/
mget $file-name
bye
EOF
该脚本首先判断有没有存放数据的文件夹,若没有,建立年和年积日的文件夹;由于登入对方服务器有许多操作限制,因此需要事先定义好需要下载的文件名$file-name;该网站的数据可以免费下载,可以使用"anonymous"匿名登录,登录密码'^M'相当于“回车”的作用;语句“ftp-inv”相当于登入对方服务器,许多Cshell命令在该状态下无法使用。
以下载小时观测文件为例,下载小时广播星历文件也类似。
2 文件合并
为保证超快速轨道解算的实时性,国际IGS分析中心一般使用小时文件合并成天文件进行解算。另外,最终产品可能需要一个周或更长的时间进行解算,这需要将多天的文件合并成一个文件。这一节介绍小时文件合并和天文件合并。
合并文件之前,需要将准备合并的小时文件放到一个文件夹中,然后使用命令:
set f-day=$s$doy"0."$yy"o"
foreach s ('ls $s$doy*.$yy"o"')
if(-e $f-day)then
cat $s | awk ’/BEIN/{i=0}/END OF HEADER/{i=NR} {if(NR> i && i!=0)print $0}’≫ $f_day
else
cat $s≫ $f-day
endif
end
其中,$f-day为该站合并后天文件文件名;$s$doy*.$yy"o"为该站的小时文件名,“*”为通配符,代表小时文件的标识a~z;“if(-e $f-day)”为判断是否已经存在合成的天文件,若不存在,则将头文件和数据记录一起写入天文件中,若存在,则将标识符“END OF HEADER”之后的数据记录写入天文件中,由于每个小时文件都有头文件,使用这种判断可以避免天文件中有多个头文件。
天文件合并的方法与小时文件合并类似,仅需要将$s$doy*.$yy"o"改为$s*"0."$yy"o"即可。
值得注意的是,MGEX使用3.xx格式的多模观测数据,其数据格式与2.xx有较大区别:其一是在头文件中加入了更多的观测类型,如图1所示;其二是数据记录方式也随头文件做了修改。
图1 RINEX3.02格式文件(部分)
在该头文件中可以看出,该站观测到了G(GPS)、S(SBSA)、R(GLONASS)、E(GALILEO)、C(BDS),由于每个小时观测到的卫星系统不尽相同,因此在合并成天文件后会出现头文件观测类型和数据记录不相符的情况,这就为后续使用该观测文件埋下了隐患。为了避免这种情况发生,使头文件和数据记录统一,应该首先遍历需要合并的小时观测文件,找到头文件观测类型最多的小时文件作为天文件的头文件。因此,上述合并文件脚本可以进一步优化为
foreach s (`ls $s$doy*.$yy"o"`)
set bb=` grep -n "SYS/#/OBS TYPES" "$s" | head-1 | cut -d ":"-f 1 '
set cc=` grep -n "SYS/#/OBS TYPES" "$s" | tail-1 | cut -d ":"-f 1'
@ aa=$cc-$bb
set aa1=0
if($aa> $aa1)then
at $s | awk '/BEIN/{i=0}/END OF HEADER/{i=NR} {if(NR < i && i!=0)print $0}'≫ $f_day
endif
@ aa1=$aa
end
该脚本的目的是以头文件观测类型最多的小时文件作为天文件的头文件,其中$bb和$cc分别为查找"SYS/#/OBS TYPES"标识符的起始行和结束行,然后做差,取其差后$aa最大的小时文件的头文件作为天文件的头文件。
3 数据传输
3.1 数据传输(内网)
一般一个服务器组都是由多台服务器构成。它们之间通过内网相互联系,如图1所示。内网的跨服务器数据传输可以用以下命令:
scp root @99.99.99.1: root/data/obs/$yy
yy/$doy/*.*o./
scp -r root @99.99.99.1: root/data/nav/$yyyy/$doy./
第一个scp是从内网地址99.99.99.1的服务器中指定目录下的观测文件拷贝到运行该命令的服务器的当前路径下;第二个添加了控制“-r”,是拷贝整个文件夹。
由于命令跨服务器拷贝数据,因此需要手动输入登入服务器的用户名和密码,这使数据拷贝变得不是很方便,而设置密钥可是省略输入密码这一步骤。具体命令如下:
cd/.ssh
ssh-keygen-t rsa
将id_rsa文件中的密钥拷贝到另一台服务器的相应位置,就可以实现两台服务器数据自由传输。
图2 内网与外网
3.2 数据传输(外网)
设置密钥传输数据仅限于内网的服务器和台式机之间而外网传输可以向任意一台联网的计算机传输数据,传输数据的命令为
set file_name=igs$week$dow.sp3
set HOST="999.999.0.1"
set USER="user_name"
set PASS='secret'
ftp -inv $HOST ≪EOF
user $USER $PASS
put $file_name
bye
EOF
该命令与mget命令相似,首先登入对方服务器,再使用put命令上传。
4 自动化运行与错误提示
若是想要将脚本和软件每天都定时运行,人工方法会很繁琐,因此,可以考虑将其加载为自动化运行。将需要自动运行的脚本写入一个新文件auto当中:
30*/1 * * */bin/csh/root/shell/get-hourly>/root/log/get.log 2>&1
该命令的时间“30 */1 * * *”为每年、每月、每天的每小时30分运行“get_hourly”脚本,由于自动运行全部在后台,不会输出任何显示信息,因此将其运行中输出的信息通过“>/root/log/get.log 2>&1”赋给一个日志文件,方便检查运行的状态及出现的错误。将需要自动运行的命令全部写好后,执行“crontab auto”命令,将其加载到后台中,命令到运行时间就可以自动运行。为了防止自动运行的脚本到了规定时间还没有结束而影响其他的进程,可以用“kill”命令将其强制结束。
自动运行的情况只能在输出的log文件中查看,不能实时的发现错误并进行改正。可以在关键步骤使用飞信进行报错提醒,若是运行出现问题,飞信就会发送短信到指定的手机上。先安装Linux系统版的飞信,再利用以下脚本进行短信错误预警:
set file_name=check_file
set lstop='cat $file_name | grep ’ERROR’
if("$lstop"=="")then
echo $file_name is Normal End>/root/log/file.log 2>&1
else
echo $file_name’ is not Normal End>/root/log/file.log 2>&1
/opt/fx/fetion -mobile=188****3047 -pwd=billgis3d -to=188****3048 -msg-utf8=$file_name’ is error’-debug
echo $?
endif
其中,需要检查名为“check_file”的文件中是否有“ERROR”提示,若是没有则表示运行正常,若有,则一方面向log文件输出文件不正常,一方面登录飞信,向负责该文件生成的负责人发送短信。
5 结束语
本文根据作者的实际工作经验,总结了Linux Shell在卫星定轨软件设计中的应用,主要有数据下载与合并、文件传输、自动运行与报错等,可以为从事卫星导航定位领域的科研人员或工作人员提供参考。但本文介绍的只是利用Cshell语言作为工具,本文提到的功能也可以用其他的语言实现,这里仅是提供一种思路和手段。
[1]刘文峰,李程远,李善平.嵌入式Linux操作系统的研究[J].浙江大学学报·工学版,2004,38(4): 447-452.
[2]邹 勇,王 青,李明树.Linux内核的实施支持的研究与实现[J].计算机研究与发展,2002,39(4): 466-472.
[3]刘善平,刘文峰,王焕龙,等.Linux与嵌入式系统[M].北京:清华大学出版社,2003.
[4]景月娥.卫星定轨可视化软件的实现与应用研究[D].西安: 国家授时中心,2011.
[5]闫生超.基于BASH脚本的Unix环境下多组件部署管理框架[J].计算机系统应用,2012,21(10): 61-65.
[6]白 云,喻 莉,谢长生.一个基于Bash的轻量级构建系统的设计与实现[J].计算机科学,2013,40(11): 8-12.