进程与管道与信号与文件锁(跳板机应用)

相关的好文章推荐:

http://www.cnblogs.com/f-ck-need-u/p/7058920.html  (子进程什么时候创建及其他更详细的,请移玉步到此链接)

 


 

内存中的女神"进程"与磁盘中的睡美人"程序"

程序是二进制文件,安安静静的在磁盘上"睡觉",不会占用CPU及内存资源。

进程是执行程序的结果,游走于内存中各个区域,占用内存享用CPU的资源。(可理解为活动的文件)


 

CPU与操作系统与多任务

单核CPU在硬件设计上就是一根筋的从头到尾的执行(月底交电费的时候,也是哇凉哇凉的),而分时操作系统(linux,windows,类unix等)通过时间划片控制各个进程切换交替执行,实现软模式的多任务执行(并发执行),当有两个以上的物理CPU时,多任务执行(并发执行)才能真正意义上得以实现。

在linux系统上,通过调度进程来确定下一个将要被CPU执行的进程,进程的优先度越低,就也容易被调度进程选中并安排给CPU执行(renice命令调整进程的优先度)。当CPU要切换执行进程时,内核会为将要停止的进程并进行现场保护(将停止的进程环境保存下来),在下一次恢复的时候,再将保存的环境加载到CPU,这就是现场恢复,这样CPU就可以在当初该进程的断点开始继续执行了。linux的调度器不是单以CPU的时间片来决定要执行下一个进程,主要以进程在队列中的等待时间。


 

进程的父子关系

 

在bash环境中,执行bash命令所产生的子进程,是不会全部继承父进程的全部环境变量,一般只继承少量的环境变量(Path路径等) ,因此在脚本设计中或有计划的创建子进程实现某些功能时,考虑父进程的环境变量是否能被子进程继承是重点之一(比如Java变量,java在父进程可以运行,在脚本中却报错了,就是因为脚本(这个儿子没有继承父亲的某些彪悍的优点)没有继承父进程的java变量,所以在脚本中需要另外添加Java的变量即可。

 


 

 父子进程与前后台的关系(jobs,nohup,bg,fg,disown)

 

bash 环境下,将子进程放入后台运行,是实现无限接近并发的效果。

 


 

 进程的状态与CPU的执行(renice)

 

在当前bash环境下,当执行cp命令时,首先fork出一个bash子进程(即前台),然后在子bash执行exec加载cp程序,cp子进程进入等待队列,由于在命令行下敲的命令,所以优先级较高,调度类很快选中它。在cp这个子进程执行过程中,父进程bash会进入睡眠状态(即后台),并等待被唤醒,此刻bash无法和人类交互。当cp命令执行完毕,它将自己的退出状态码告知父进程,此次复制是成功还是失败,然后cp进程自己消逝掉,父进程bash被唤醒再次进入等待队列,并且此时bash已经获得了cp退出状态码,根据状态码这个"信号",父进程bash知道了子进程已经终止,所以通告给内核,内核收到通知后将进程列表中的cp进程项删除。至此,整个cp进程正常完成。

 

僵尸进程的出现,是因为子进程在没有执行完毕之前,自己的父进程被某人kill(送到很远的地方了)了,这样父进程就没有法子通知内核做清理回收了(清理门户),这样子进程就没有户口了,内核只能将子进程领养了,放入养老院了(命令top 中的字段 zombie 进行查看)。

 


 

 信号与进程(kill,pkill,killall,trap)

信号是软件层次上对(硬)中断的一种模拟,通知进程发送了什么事件(而不是对进程传递数据),令进程改变某些行为。信号是操作系统规范进程改变自身的一种行为。

一般情况下完善的程序设计,在子进程终止、退出的时候,会发送SIGCHLD信号给父进程,父进程收到信号就会通知内核清理该子进程相关信息。

同时,信号也提供了人工干预进程的方式。

信号的种类

[root@server01 ~]# kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
[root@server01
~]#

 

 

常用的信号

 
SIGHUP1终端退出时,此终端内的进程都将被终止
SIGINT2中断进程,可被捕捉和忽略,几乎等同于sigterm,所以也会尽可能的释放执行clean-up,释放资源,保存状态等(CTRL+C)
SIGQUIT3从键盘发出杀死(终止)进程的信号(ctrl + /)
SIGABRT6中止,执行错误引起
SIGKILL9强制杀死进程,该信号不可被捕捉和忽略,进程收到该信号后不会执行任何clean-up行为,所以资源不会释放,状态不会保存
SIGALRM14报警,处理超时
SIGTERM15杀死(终止)进程,可被捕捉和忽略,几乎等同于sigint信号,会尽可能的释放执行clean-up,释放资源,保存状态等
SIGCHLD17

当子进程中断或退出时,发送该信号告知父进程自己已完成,父进程收到信号将告知内核清理进程列表。

所以该信号可以解除僵尸进程,也可以让非正常退出的进程工作得以正常的clean-up,释放资源,保存状态等。

SIGCONT18

发送此信号使得stopped进程进入running,该信号主要用于jobs,例如bg & fg 都会发送该信号。

可以直接发送此信号给stopped进程使其运行起来

SIGSTOP19该信号是不可被捕捉和忽略的进程停止信息,收到信号后会进入stopped状态
SIGTSTP20停止进程的运行,该信号是可被忽略的进程停止信号(CTRL+Z)
   

 

信号的发送方式(命令方式与组合键方式)

killpkillkillall键盘上的组合键

 

  ctrl + d;ctrl + c ;ctrl + z 等

 

信号捕获(trap) 

 

查看信号的种类

(效果与kill -l一致)

[root@server01 ~]# trap -l

发生对应的信号

触发相应的命令

trap 'command' signals

[root@server01 ~]# trap 'echo "是谁按下ctrl+c的,站起来,让我认下。"' INT #按下ctrl+c,触发INT信号,执行对应的命令
[root@server01 ~]# ^C是谁按下ctrl+c的,站起来,让我认下。

[root@server01 ~]# 

取消信号触发的命令

trap  signals

[root@server01 ~]# trap -p # 查当前有多少个信号被捕获
trap -- 'echo "是谁按下ctrl+c的,举个手,让我认下。"' SIGINT
[root@server01 ~]# trap 2 # 取消 2 信号的设置,数值 2 对应 SINGINT
[root@server01 ~]# trap -p

 一次设置多个信号触发命令

其中20信号在脚本生效

[root@server01 ~]# trap '' 1 2 3 15 20 
[root@server01 ~]# trap -p
trap -- '' SIGHUP
trap -- '' SIGINT
trap -- '' SIGQUIT
trap -- '' SIGTERM
[root@server01 ~]# 
 输入信号字母也可以
[root@server01 ~]# trap 'echo "按啥都没有,乖乖的做事。"' HUP INT QUIT TERM TSTP
[root@server01 ~]# trap -p
trap -- 'echo "按啥都没有,乖乖的做事。"' SIGHUP
trap -- 'echo "按啥都没有,乖乖的做事。"' SIGINT
trap -- 'echo "按啥都没有,乖乖的做事。"' SIGQUIT
trap -- 'echo "按啥都没有,乖乖的做事。"' SIGTERM
[root@server01 ~]# 
 一次取消多信号触发命令
[root@server01 ~]# trap - 1 2 3 15 20  
[root@server01 ~]# trap -p
[root@server01 ~]# 

 

trap 一般用于当进程发生人为或意外终止的时候,用于清理善后工作
窗口1窗口2,执行命令后,观察文件如何生产,切换到窗口1按下ctrl+c后,又是如何删除文件的
[root@server01 tmp]# cat touch_file.sh      
#!/bin/bash
trap "find /tmp -type f -name 'test_*' |xargs rm -f && exit " INT
while :
do 
  touch /tmp/test_$(date +%F-%T)
  usleep 5000
done
[root@server01 tmp]# bash touch_file.sh

 

[root@server01 tmp]# watch ls








 

 


 

 进程与信号实现跳板机

 

跳板机核心实现的相关代码
信号脚本登录脚本测试效果
[root@server01 tmp]# cat tb.sh 
#!/bin/bash
function menu()
{
# EOF前的‘-’,是配合最后一个tab+EOF的结束,
  cat <<-EOF
======Host List======
1) 192.168.6.95
2) 192.168.6.96
3) exit
        EOF
}

function host()
{
  case "$1" in
  1)
    ssh -p22 192.168.6.95
    ;;
2)
ssh -p22 192.168.6.96
*) exit ;; esac } function main() { trap '' INT QUIT TSTP TERM HUP while : do clear menu read -p 'please select:' num host $num done } main [root@server01 tmp]#

 

[root@server01 ~]# cat /etc/profile.d/tb.sh 
[ $UID -ne 0 ] && [ $USER != 'bonuo' ] &&\
source /tmp/tb.sh
#exec /tmp/tb.sh 
# 使用exec取代source也是可以的。
# 账号bonuo是SSH连上跳板机的后门账号
# UID=0的账号,是让bonuo登录后执行 su - 切换root,来管理跳板机 [root@server01
~]#































 

重新登录时出现以下提示:

======Host List======
1) 192.168.6.95
2) 192.168.6.96
3) exit
please select:

 

 


 

进程与管道(xargs)

 

无名管道(pipe):

 

在Linux下,你可以通过"|"连接两个程序,这样就可以用它来连接后一个程序的输入和前一个程序的输出,因此被形象地叫做个管道。父进程往第一个文件描述符里头写入东西后,子进程可以从第一个文件描述符中读出来。

实际上当我们输入这样一组命令的时候(echo "hi fd" | cat ),前面一个进程的输出关联(重定向)到管道的输出文件描述符,把后面一个进程的输入关联到管道的输入文件描述符。注意:两个命令都要同时存在。

 

 

进程echo将内容到标准输出(文件描述符为fd 1)连接到了管道的写入端,读取进程cat就将其标准输入(文件描述符为fd 0)连接到了管道的输出端。实际上,这两个进程并不知道管道的存在,它们只是从标准文件描述符中读取数据和写入数据。(文件描述符可以参考此处

 

xargs

 

 详细的细节,请指尖微点一下(骏马金龙)此处

 

有名管道(named pipe)


有名管道实际上是一个文件(无名管道也像一个文件,虽然关系到两个文件描述符,不过只能一边读另外一边写),不过这个文件比较特别,操作时要满足先进先出,而且如果试图读一个没有内容的有名管道,那么就会被阻塞(等待数据过来),同样地,如果试图往一个有名管道里头写东西,而当前没有程序试图读它,也会被阻塞(等待数据被读取)。

有名管道与无名管道的区别:有名管道将无名管道的两边进程(同时存在的写与读)分别独立出来,通过一个中间的文件进行数据传递,因此有名管道特别适合有两个独立程序构成某些任务的模式(可以理解A程序实现菜单及对应的功能,B程序实现read读取用户选择,而有名管道实现B程序传参给A程序),如A程序(类似一个脚本无限的循环菜单,及菜单对应的功能)无限循环的读取有名管道文件,通过获取数据,对应执行那些事件(若没有数据,则阻塞从而避免无限循环导致资源浪费),B程序(类似read命令,读取用户的输入)则作为控制程序往有名管道文件输入指令。

 

 
窗口1窗口2
[root@server01 tmp]# mkfifo fifo_a
[root@server01 tmp]# echo "hello" > fifo_a 
[root@server01 tmp]# echo "hello again" > fifo_a


 

[root@server01 tmp]# cat fifo_a 
hello
[root@server01 tmp]# cat fifo_a 
hello again
[root@server01 tmp]#

 

 

 

 


 

进程的并发与文件锁(flock)~劝告锁(advisory lock)

 

Linux中软件、硬件资源都是文件(一切皆文件),文件在多用户环境中是可共享的。当多个进程共享一个资源进行操作时,会出现一些不可预见的情况。

 

并发的威力与预期偏差
代码(2000个1累加)效果(原来并发也可以做随机数哦,只是我用的不是神威,奢侈不起。)
 
[root@server01 ~]# cat a.sh 
#!/bin/bash
countfile=/tmp/count
echo 0 > $countfile

do_count(){
echo $((`cat $countfile`+1)) > $countfile

}

for i in `seq 1 2000`
do
  do_count &
done

wait

cat $countfile
rm $countfile


[root@server01
~]#

 

 
[root@server01 ~]# bash a.sh 
1999
[root@server01 ~]# bash a.sh 
1366
[root@server01 ~]# bash a.sh 
580
[root@server01 ~]# bash a.sh 
78
[root@server01 ~]# bash a.sh 
192
[root@server01 ~]# bash a.sh 
1992
[root@server01 ~]# bash a.sh 
1899
[root@server01 ~]# bash a.sh 
2000
[root@server01 ~]# bash a.sh 
268
[root@server01 ~]# bash a.sh 
1762
[root@server01 ~]# bash a.sh 
1888
[root@server01 ~]#

 

 

 

劝告锁是一种协同工作的锁。对于这一种锁来说,内核只提供加锁以及检测文件是否已经加锁的手段,但是内核并不参与锁的控制和协调。用于解决资源共享所使用的一种约定机制(不强制)实现并发的控制(如:在执行一个周期性的定时任务脚本时,当脚本执行时间过长,导致上一次的任务没有完成,当下又开始新的执行,可能会导致并发出现,严重时会导致出现脏数据/性能瓶颈的恶性循环。)

劝告锁的本质是为"资源"创建另一个文件,该文件(锁文件)告诉其他的进程该资源已被"使用"(也就是其他进程在调用该资源的时候,先去检查该资源的锁文件是否存在,存在则表示该资源被使用中,反之表示该资源没有被使用。)。linux 提供的flock命令能自动创建该资源的锁文件,当使用该资源的进程结束时,自动对锁文件解锁。

根据文件锁的方式,可以通过创建一个临时文件来充当锁文件,当这个文件存在,则说明有程序在执行;如果不存在,则说明没锁,可以去执行。如果还想完整一点的,可以向这个锁文件里写点内容,根据内容来判断锁是否存在、是读锁、还是写锁。

  

flock [-sxon] [-w timeout] lockfile [-c] command...
flock [-sxun] [-w timeout] fd

-s,--shared:获取一个共享锁,在定向为某文件的FD上设置共享锁而未释放锁的时间内,其他进程试图在定向为此文件的FD上设置独占锁的请求失败,而其他进程试图在定向为此文件的FD上设置共享锁的请求会成功。
-x,-e,--exclusive:获取一个排它锁,或者称为写入锁,为默认项
-u,--unlock:手动释放锁,一般情况不必须,当FD关闭时,系统会自动解锁,此参数用于脚本命令一部分需要异步执行,一部分可以同步执行的情况。
-n,--nb, --nonblock:非阻塞模式,当获取锁失败时,返回1而不是等待
-w, --wait, --timeout seconds:设置阻塞超时,当超过设置的秒数时,退出阻塞模式,返回1,并继续执行后面的语句
-o, --close:表示当执行command前关闭设置锁的FD,以使command的子进程不保持锁。
-c, --command command:在shell中执行其后的语句

  

flock常用的选项 -x -n -w -c
窗口1窗口2:新的进程无法启动,因为a.sh被调用,直到a.lock解锁后才能调用a.sh
[root@server01 tmp]# ls
a.sh
[root@server01 tmp]# cat a.sh 
#!/bin/bash
echo "lock is start"
sleep 30
echo "unlocked"
[root@server01 tmp]#
[root@server01 tmp]# flock -xn ./a.lock -c "bash a.sh"
lock is start

 

[root@server01 tmp]# flock -xn ./a.lock -c "bash a.sh"
[root@server01 tmp]# flock -xn ./a.lock -c "bash a.sh"
[root@server01 tmp]# flock -xn ./a.lock -c "bash a.sh"
[root@server01 tmp]# flock -xn ./a.lock -c "bash a.sh"
[root@server01 tmp]# ls
a.lock  a.sh




 

 

 


 

 

进程PID与相关文件的常用命令

收集相关的命令并汇总,(不定期更新)

 

相关进程命令根据文件反查进程 综合类
pstree 查看当前环境进程的父子进程关系

 

[root@server01 ~]# pstree
init─┬─crond
     ├─6*[mingetty]
     ├─rsyslogd───3*[{rsyslogd}]
     ├─sshd───sshd─┬─bash───pstree
     │             └─bash
     └─udevd───2*[udevd]
[root@server01 ~]# 

 

源自:骏马金龙

fuser [-ki] [-signal] file/dir
-k:找出文件或目录的pid,并试图kill掉该pid。发送的信号是SIGKILL -i:一般和-k一起使用,指的是在kill掉pid之前询问。 -signal:发送信号,如-1 -15,如果不写,默认-9,即kill -9 不加选项:直接显示出文件或目录的pid

 示例:

窗口1:
[root@server01 ~]# tail -f a.sh 

窗口2:
[root@server01 ~]# fuser a.sh 
a.sh:                 1056
[root@server01 ~]# fuser -k a.sh 
a.sh:                 1056
[root@server01 ~]# fuser -k a.sh 
[root@server01 ~]# 

 

源自:骏马金龙

 

lsof /path/to/somefile:显示打开指定文件的所有进程之列表;建议配合grep使用
lsof -c string:显示其COMMAND列中包含指定字符(string)的进程所有打开的文件;可多次使用该选项
lsof -p PID:查看该进程打开了哪些文件
lsof -U:列出套接字类型的文件。一般和其他条件一起使用。如lsof -u root -a -U
lsof -u uid/name:显示指定用户的进程打开的文件;可使用脱字符"^"取反,如"lsof -u ^root"将显示非root用户打开的所有文件
lsof +d /DIR/:显示指定目录下被进程打开的文件
lsof +D /DIR/:基本功能同上,但lsof会对指定目录进行递归查找,注意这个参数要比grep版本慢
lsof -a:按"与"组合多个条件,如lsof -a -c apache -u apache
lsof -N:列出所有NFS(网络文件系统)文件
lsof -n:不反解IP至HOSTNAME
lsof -i:用以显示符合条件的进程情况
lsof -i[46] [protocol][@host][:service|port]
  46:IPv4或IPv6
  protocol:TCP or UDP
  host:host name或ip地址,表示搜索哪台主机上的进程信息
  service:服务名称(可以不只一个)
  port:端口号 (可以不只一个)

 

输出信息中各列意义:

COMMAND:进程的名称
PID:进程标识符
USER:进程所有者
FD:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等
TYPE:文件类型,如DIR、REG等
DEVICE:指定磁盘的名称
SIZE/OFF:文件的大小或文件的偏移量(单位kb)(size and offset)
NODE:索引节点(文件在磁盘上的标识)
NAME:打开文件的确切名称

   

转载于:https://www.cnblogs.com/BoNuo/articles/9732810.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值