Linux下shell执行程序
原理
Linux操作系统下shell脚本是开发项目中是比较常用的。shell脚本是如何被Linux系统所调用执行的呢,首先我们以ps命令为例,来解释一下shell脚本是如何被系统执行的。
命令:ps -o pid,ppid,pgid,sid,comm
其中:pid:自身进程id,ppid:父进程id,pgid:所属进程组id,sid:所属会话id,comm:命令。
在Linux系统下执行程序结果如下:
由上图可以看到,ps的父进程为bash,这正是我们所希望的。bash和ps命令两者位于同一会话和前台进程(1982)。不同的终端连接系统时bash所属会话和进程组都不一样,因此每个终端有自身的所属会话和进程组。
Shell调用本质其实是由shell(该系统的shell类型为bash)调用fork()函数创建一个进程,由该创建的子进程去调用一种exec函数去执行另一个程序。当子进程调用一种exec函数时,该子进程的执行的程序完全替换为新进程,因为调用exec函数并不创建新进程,所有前后进程的进程ID并不改变。exec程序只是用一个全新程序替换了当前进程的正文,数据、堆和栈。举个比较形象的例子,就好像一栋大楼里面刚开始是腾讯公司在里面办公,后来倒闭了,里面搬进了阿里巴巴公司,尽管大楼内的部署跟执行的任务已经改变,但这栋大楼还是之前的大楼。
在Linux系统下shell如果在一个管道中执行三个进程我们可以检验一下bash使用的进程控制方式。如下:
由上实验我们可知,bash使用的进程控制方式是:在执行每个命令调用时,都会由bash自身创建一个进程,然后由创建的子进程去调用exec函数去执行调用命令,而且bash创建的所有进程与bash同属一个会话(session id : 3983);而所有的子进程同属一个进程组(gpid:7151),该进程组ID为进程ps命令所属进程ID。如下:
实例
笔者在项目开发中遇到过这种情况,需要在后台跑一个shell脚本程序,名称为test_lijd.sh。该脚本的任务是定时获取系统信息,当然这并不重要。在该进程执行前需检测有没有同名的进程(名称为test_lijd.sh)已经在运行,如果有,则立刻退出,没有则起该进程去完成任务。
代码 lijd_test.sh 如下:
[code]#!/bin/bash ######################## #filename : lijd_test.sh #auth : lijd #data : 2018-12-27 ######################## main() { process_num=`ps aux | grep lijd_test.sh | grep -v grep |wc -l` if [ $process_num -gt 0 ] then printf 'process_num : '$process_num'\n' printf 'lijd_test.sh process has exist!\n' exit -1 fi while [ 1 ] do printf 'this is test!\n' sleep 30 done } main
运行结果如下:
运行该脚本前执行运行进程数为0。在脚本中执行,可以看到该运行进程数为:2。
运行结果为什么是2?其中有一个为当前自身正在运行的进程,另一个则是在执行ps命令时由bash创建的子进程去调用,该进程名中也包含关键字lijd_test.sh。
那么如何实现这种功能呢?给计算除的结果减2看等不等于0?这种方法简单,但经过在不同的Linux系统做实验,有的Linux系统用这种方法依旧存在问题,由于不同Linux系统下使用的shell类型不同。
笔者提供一种方法,代码重新修改后如下:
[code]#!/bin/bash ####################### #filename: lijd_test.sh #auth : lijd #data : 2018-12-27 ####################### function cheak_myself_process () { ps -ef 1>/tmp/process.log while read line do flag=`awk 'BEGIN {if (match(ARGV[ARGC-1], "lijd_test\\.sh$") != 0) print "true"; else print "false"}' $line 2>/dev/null` if [ "${flag}" == "true" ] then auto_bypass_num+=1 fi done </tmp/process.log rm -rf /tmp/process.log } main() { declare -i process_num=0 cheak_myself_process if [ $process_num -gt 0 ] then printf 'process_num : '$process_num'\n' printf 'lijd_test.sh process has exist!\n' exit -1 fi while [ 1 ] do printf 'this is test!\n' sleep 30 done } main
运行结果如下:
对于此篇博客存在的问题,欢迎各位大佬指正留言。
- linux下写C程序,执行shell文件
- Linux(Ubuntu)下设置开机启动shell脚本执行Java程序jar包
- linux 使用 java 程序执行 shell命令
- linux下C程序插入执行shell脚本
- Linux环境中通过c程序执行shell脚本
- 从Linux程序中执行shell(程序、脚本)并获得输出结果(转)
- linux下写C程序,执行shell文件
- Linux下C程序插入执行shell脚本
- 从Linux程序中执行shell(程序、脚本)并获得输出结果(转)
- linux下写C程序,执行shell文件
- Linux库文件和Shell可执行程序命令文件搜索路径变量的设置
- windows 下 java程序jsch连接远程linux服务器执行shell命令
- 在linux编写shell程序并执行
- 从Linux程序中执行shell(程序、脚本)并获得输出结果
- linux的shell命令检测某个java程序是否执行
- 从Linux程序中执行shell(程序、脚本)并获得输出结果
- Unix/Linux中后台运行程序(断开shell连接后继续执行)的几种方式
- 从Linux程序中执行shell(程序、脚本)并获得输出结果
- 从Linux程序中执行shell(程序、脚本)并获得输出结果
- linux的shell命令检测某个java程序是否执行