Bonky Zhu
If someone is able to show me that what I think or do is not right, I will happily change, for I seek the truth, by which no one was ever truly harmed. It is the person who continues in his self-deception and ignorance who is harmed.

Linux 进程管理

Linux 的进程

fork and exec

Linux 下进程间相互调用的方式称为 fork-and-exec。父进程通过 fork 的方式产生一个一模一样的子进程,然后被复制出来的子进程再以 exec 的方式来执行实际要进行的进程,最终成为一个子进程的存在。整个流程如下:

image-20200211184125735

(1) 系统先 fork 复制一个与父进程相同的暂存进程,与父进程唯一的差别就是 PID 不同。但是这个暂存进程还会多一个 PPID 的参数,PPID 是父进程的进程标识符。

(2) 暂存进程开始以 exec 的方式加载实际要执行的程序,以上述图标来讲,新的程序名称为 qqq ,最终子进程的程序代码就会变成 qqq 。

服务(deamon)

服务是常驻在内存的进程,如:crond,atd。其实 crond 和 atd 最后一个 d 都是 deamon 的意思,所以说一般来说以 d 结尾的很有可能是某种服务。

作业管理

后台执行 &[C+z]

& 是让程序后台执行,但不过还是会有 stdout 和 stderr,我们可以利用数据流重定向来后台运行:

➜  ~ find / -print >/tmp/log.txt 2>&1 &
[1] 31120


无需要等待,直接放在后台执行。对于后台执行的任务,我们可以利用 jobs 进行查看:

➜  jobs [-lrs] 
选项与参数:
-l :除了列出 job number 与指令串之外,同时列出 PID 的号码;
-r :仅列出正在背景 run 的工作;
-s :仅列出正在背景当中暂停 (stop) 的工作。


查看结果如下,其中 + 号意味着最近一个后台运行的程序:

➜  ~ jobs -l
[1]  + 31120 running    find / -print > /tmp/log.txt 2>&1


fg 和 bg 也是两个非常重要的指令,fg 的作用是把后台运行的程序放到前台来运行,bg 的作用是把后台终止的程序继续运行:

➜  [fg|bg] %jobnumber
选项与参数:
%jobnumber :jobnumber 为工作号码(数字)。


如果想要杀死一个 job,请使用 kill:

➜  kill -signal [ %jobnumber | PID ] 
选项与参数:
-l :这个是 L 的小写,列出目前 kill 能够使用的讯号 (signal) 有哪些?
signal :代表给予后面接的那个工作什么样的指示啰!用 man 7 signal 可知:
  -1 :重新读取一次参数的配置文件 (类似 reload);
  -2 :代表与由键盘输入 [ctrl]-c 同样的动作;
  -9 :立刻强制删除一个工作;
  -15:以正常的进程方式终止一项工作。与 -9 是不一样的。(默认为 -15 )


注意,-9 选项适合退出那些不正常工作的程序,对于正常运行的程序,应该用 -15 选项或者不填。当使用 vim 的时候,会产生 .swp 文件。 那么,当使用 -15 时, vim 会尝试以正常的步骤来结束掉该 vim 的工作, 所以交换文件会被移除。但若是使用 -9 时,vim 被强制退出,因此, 交换文件就会继续存在文件系统当中。

注意你输入 -l 选项,你可以发现以下选项:

HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS


上面这些是 Unix 所支持的信号,其实 kill 就是给响应进程/工作一个信号,这些信号按照顺序分别编号为 1 ~ 31。注意这些信号都是不可靠信号(非实时的),后来又扩充了一些信号编号为 32~63,是可靠信号(实时的)。不可靠信号和可靠信号的区别在于前者不支持排队,可能会造成信号丢失,而后者不会。

Linux 信号

代号 名称 内容
1 SIGHUP 1. 在用户终端连接结束时发出,通知同一session内的各个作业,终止进程(一般来说是对有输入输出的进程)。如果我们忽略 HUP 信号,这样就算退出了登录,也能继续执行(nohup 原理)。。

2. 对于与终端脱离关系的守护进程,这个信号用于通知它重新读取配置文件

2 SIGINT 相当于用键盘输入 [ctrl]-c 来中断一个进程的进行
9 SIGKILL 强制中断一个进程的进行。
15 SIGTERM 以正常的结束进程来终止该进程。
19 SIGSTOP 相当于用键盘输入 [ctrl]-z 来暂停一个进程的进行

登出不退出:nohup,tmux

➜  nohup [指令与参数]     <==在终端机前景中工作
➜  nohup [指令与参数] & <==在终端机后台中工作


而 tmux 是新建一个不会随着登出而关闭的 shell,常用的操作如下:

  • 建立会话: tmux new -s 会话名
  • ctrl+b d 退出会话,回到shell的终端环境,会话在后台运行
  • tmux ls 终端环境查看会话列表
  • tmux a -t 会话名 从终端环境进入会话
  • tmux kill-session -t 会话名 销毁会话

进程管理

ps 指令

➜  ps aux  <==观察系统所有的进程数据
➜  ps -lA  <==也是能够观察所有系统的数据
➜  ps axjf <==连同部分进程树状态
选项与参数:
-A :所有的 process 均显示出来,与 -e 具有同样的效用;
-a :不与 terminal 有关的所有 process ;
-u :有效使用者 (effective user) 相关的 process ;
x :通常与 a 这个参数一起使用,可列出较完整信息。
输出格式规划:
  l :较长、较详细的将该 PID 的的信息列出;
  j :工作的格式 (jobs format)
  -f :做一个更为完整的输出。


使用 -l 选项我们可以查看详细信息:

➜  ~ ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0  3222  3212  0  80   0 - 35158 sigsus pts/0    00:00:00 zsh
0 R     0  4749  3222  0  80   0 - 38312 -      pts/0    00:00:00 ps
➜  ~ ps aux | grep 3212
root      3212  0.0  0.2 158948  3936 ?        Ss   19:43   0:00 sshd: root@pts/0

  • F:代表这个进程旗标 (process flags),说明这个进程的总结权限,常见号码有:
    • 若为 4 表示此进程的权限为 root
    • 若为 1 则表示此子进程仅进行复制(fork)而没有实际执行(exec)
    • 若为 0 代表正在执行
  • S:代表这个进程的状态 (STAT),主要的状态有:
    • R (Running):该程序正在运作中;
    • S (Sleep):该程序目前正在睡眠状态(idle),但可以被唤醒(signal)。
    • D :不可被唤醒的睡眠状态,通常这支程序可能在等待 I/O 的情况(ex>打印)
    • T :停止状态(stop),可能是在工作控制(背景暂停)或除错 (traced) 状态;
    • Z (Zombie):僵尸状态,进程已经终止但却无法被移除至内存外。
  • UID/PID/PPID:我们可以注意到 ps 选项的 PPID 是 zsh 的 PID,zsh 的 PPID 是 sshd(ssh 的服务)。
  • C:代表 CPU 使用率,单位为百分比
  • PRI/NI:Priority/Nice 的缩写,代表此进程被 CPU 所执行的优先级,数值越小代表该进程越快被 CPU 执行。
  • ADDR/SZ/WCHAN:都与内存有关,ADDR 是 kernel function,指出该进程在内存的哪个部分,如果是个 running 的进程,一般就会显示 - 。SZ 代表此进程用掉多少内存。WCHAN 表示目前进程是否运作中,同样的, 若为 - 表示正在运作中。
  • TTY:登入者的终端机位置,若为远程登录则使用动态终端接口 (pts/n);
  • TIME:使用掉的 CPU 时间,注意,是此进程实际花费 CPU 运作的时间,而不是系统时间。
  • CMD:所执行的指令。

其中 -f 选项可以看到进程树:

➜  ~ ps f
  PID TTY      STAT   TIME COMMAND
 9315 tty3     Ss+    0:00 -zsh
 3222 pts/0    Ss     0:00 -zsh
12314 pts/0    R+     0:00  \_ ps f


其实用 pstree 更加直观:

➜  ~ pstree
systemd─┬─AliYunDun───21*[{AliYunDun}]
        ├─AliYunDunUpdate───3*[{AliYunDunUpdate}]
        ├─BT-Panel───{BT-Panel}
        ├─CmsGoAgent.linu─┬─exe───8*[{exe}]
        │                 └─6*[{CmsGoAgent.linu}]
        ├─Plex Media Serv─┬─Plex DLNA Serve───11*[{Plex DLNA Serve}]
        │                 ├─Plex Script Hos───12*[{Plex Script Hos}]
        │                 ├─Plex Tuner Serv───12*[{Plex Tuner Serv}]
        │                 └─16*[{Plex Media Serv}]
            (下面太多了所有省略)


top 指令

有点类似于任务管理器的作用:

➜  top [-d 数字] | top [-bnp]
选项与参数:
-d :后面可以接秒数,就是整个进程画面更新的秒数。预设是 5 秒; 
-b :以批次的方式执行 top ,还有更多的参数可以使用喔! 通常会搭配数据流重导向来将批次的结果输出成为文件。
-n :与 -b 搭配,意义是,需要进行几次 top 的输出结果。
-p :指定某些个 PID 来进行观察监测而已。
在 top 执行过程当中可以使用的按键指令:
  ? :显示在 top 当中可以输入的按键指令;
  P :以 CPU 的使用资源排序显示;
  M :以 Memory 的使用资源排序显示;
  N :以 PID 来排序喔!
  T :由该 Process 使用的 CPU 时间累积 (TIME+) 排序。
  k :给予某个 PID 一个讯号 (signal),可以用来杀进程。
  r :给予某个 PID 重新制订一个 nice 值。
  q :离开 top 软件的按键。


killall:根据名字杀进程

killall [-iIe] [command name]
选项与参数:
-i :interactive 的意思,交互式的,若需要删除时,会出现提示字符给用户。
-e :exact 的意思,表示要与 command name 完全要一致,但不能超过 15 个字符。
-I :指令名称(可能含参数)忽略大小写。


Linux 进程的执行优先级

执行优先级主要靠 Priority 与 Nice 值来决定:

  • 执行级越高,越优先执行
  • 每次执行完后,就进行运行 PRI(new) = PRI(old) + NICE
  • 如果 NICE 值为负值的时候,一开始优先级高的可能降低,一开始低的可以执行。

系统资源的观察

free:查看内存用量

➜  free [-b|-k|-m|-g|-h] [-t] [-s N -c N]
选项与参数:
[-b|-k|-m|-g|-h] :显示的单位 (h=human)
-t :在输出的最终结果,显示物理内存与 swap 的总量。
-s :可以让系统每几秒钟输出一次,不间断的一直输出的意思!对于系统观察挺有效!
-c :与 -s 同时处理~让 free 列出几次的意思~


一般来说 free -h 用的最多,方便于查看

uname:查阅系统与核心相关信息

➜  uname [-asrmpi]
选项与参数:
-a :所有系统相关的信息,包括底下的数据都会被列出来;
-s :系统核心名称
-r :核心的版本
-m :本系统的硬件名称,例如 i686 或 x86_64 等;
-p :CPU 的类型,与 -m 类似,只是显示的是 CPU 的类型!
-i :硬件的平台 (ix86)


netstat:查看网络信息

➜  netstat -[atunlp]
选项与参数:
-a :将目前系统上所有的联机、监听、Socket 数据都列出来
-t :列出 tcp 网络封包的数据
-u :列出 udp 网络封包的数据
-n :不以进程的服务名称,以埠号 (port number) 来显示;
-l :列出目前正在网络监听 (listen) 的服务;
-p :列出该网络服务的进程 PID


显示的结果一般都是以下格式:

➜  ~ netstat -nlp
Active Internet connections (only servers)  # 与网络较相关的部分
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      1844/cupsd
......(省略)......
Active UNIX domain sockets (only servers)   # 本机进程自己的相关性(非网络)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
unix  2      [ ACC ]     STREAM     LISTENING     18687    1/systemd            ......(省略)......

  • Recv-Q,Send-Q:接受队列和发送队列
  • RefCnt:连接到此 socket 的进程数量;

dmesg:分析核心产生的信息

➜  ~ dmesg | more
[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Initializing cgroup subsys cpuacct


vmstat :侦测系统资源变化

下面我们检查系统资源使用情况,每隔一秒一次,一共三次:

➜  ~ vmstat 1 3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0  19968  71260      0 1060984    0    1   131     9  349  624  1  1 98  0  0
 0  0  19968  71028      0 1060984    0    0     0    48  294  497  0  1 99  0  0
 0  0  19968  70940      0 1060984    0    0     0     0  286  487  1  1 99  0  0


上面字段的含义如下:

  • 如果 si/so 的数值太大,表示内存内的数据常常得在磁盘与主存储器之间传来传去,系统效能会很差。
  • bi/bo 中的 b 代表 block。如果这部份的值越高,代表系统的 I/O 非常忙碌。
  • 对于 system 区,in 代表每秒被中断的进程次数; cs 代表每秒钟进行的事件切换次数;这两个数值越大,代表系统与设备的沟通非常频繁。包括磁盘、网卡等。
  • CPU 的项目分别为:us 用户态运行时间; sy 核心态运行时间; id 闲置的时间; wa 等待 I/O 所耗费的 CPU 状态; st 被虚拟机所使用的 CPU 使用状态。

特殊文件和进程

SUID,SGID 和 SBIT

SUID (Set UID)

/bin/passwd 文件,他的权限为 -rwsr-xr-x,可以注意到对于拥有者他的执行权限不是 x 而是 s,这代表 SUID。SUID 的特点如下:

  • SUID 权限仅对二进制程序有效;
  • 执行者对于该程序需要具有 x 的可执行权限;
  • 本权限仅在执行该程序的过程中有效;
  • 执行者将具有该程序拥有者的权限。

下面有一张图可以说明没有 SUID 的二进制程序执行的区别:

image-20200213161507948

可以看出对于用户,有 SUID 权限的相当于文件拥有者在操作,而没有的相当于当前用户在操作。

SGID (Set GID)

和 SUID 类似,只不过执行的权限拥有的是文件拥有群组,群组的 x 变成了 s。其次,SGID 不仅可以设置文件还可以设置目录:

  • 用户若对于此目录具有 r 与 x 的权限时,该用户能够进入此目录;
  • 用户在此目录下的有效群组(effective group)将会变成该目录的群组;
  • 用途:若用户在此目录下具有 w 的权限(可以新建文件),则使用者所建立的新文件,该新文件的群组与此目录的群组相同。

SBIT (Sticky Bit)

仅能对目录有用,对于其它用户执行权限是 T,drwxrwx--T.。当用户对于此目录具有写入的权限时,在该目录下建立文件或目录时,仅有自己与 root 才有权力删除该文件。

修改 SUID,SGID 和 SBIT 的方法

修改的时候同样使用 chmod,只要在原来的三个数字前面加上第四个数字就好了。其中,4 为 SUID,2 为 SGID,1 为 SBIT。

➜  ~ ll
-rwxr-xr-x.  1 root root 7.1K 2月  13 16:27 python
➜  ~ chmod 6777 python
➜  ~ ll
-rwsrwsrwx.  1 root root 7.1K 2月  13 16:27 python


可以看到 python 的用户和群组的执行权限都变成了 s 。当我们想要找系统中所有的有特殊权限的,可以使用 find 指令:find / -perm /6000

/proc

/proc 下数字代表的是对应 PID 的进程,除此之外还有一些特殊的文件:

檔名 文件内容
cmdline 加载核心的参数
cpuinfo CPU 的相关信息
loadavg 还记得 top 以及 uptime 吧?没错!上头的三个平均数值就是记录在此!
meminfo 使用 free 列出的内存信息,嘿嘿!在这里也能够查阅到!
modules 目前我们的 Linux 已经加载的模块列表,也可以想成是驱动程序啦!
partitions 使用 fdisk -l 会出现目前所有的 partition 吧?在这个文件当中也有纪录喔!

文件与进程

fuser:检查占用文件的进程

使用方法如下:

➜  fuser [-umv] [-k [i] [-signal]] file/dir
选项与参数:
-u :除了进程的 PID 之外,同时列出该进程的拥有者;
-m :显示文件所在文件系统所有的占用情况,对 umount 不成功很有效!
-v :可以列出每个文件与进程还有指令的完整相关性!
-k :找出使用该文件/目录的 PID ,并试图以 SIGKILL 这个讯号给予该 PID;
  -i :必须与 -k 配合,在删除 PID 之前会先询问使用者意愿!
  -signal:例如 -1 -15 等等,若不加的话,预设是 SIGKILL (-9) 啰!


注意一下,对于 vim,不会占用原来的打开文件,而是会占用其生成的临时的交换文件:

➜  ~ fuser -uv ~/.anaconda-ks.cfg.swp
                     用户     进程号 权限   命令
/root/.anaconda-ks.cfg.swp:
                     root      14920 F.... (root)vim


注意对于权限(英文 ACCESS)那一行意义如下:

  • c :此进程在当前的目录下(非次目录);
  • e :可被触发为执行状态;
  • f :是一个被开启的文件;
  • r :代表顶层目录 (root directory);
  • F :该文件被开启了,不过在等待回应中;
  • m :可能为分享的动态函式库;
  • lsof:检查进程所打开的文件
➜  lsof [-aUu] [+d]
选项与参数:
-a :多项数据需要『同时成立』才显示出结果时!
-U :仅列出 Unix like 系统的 socket 文件类型;
-u :后面接 username,列出该使用者相关进程所开启的文件;
+d :后面接目录,亦即找出某个目录底下已经被开启的文件!


检查在家目录中 vim 打开的文件:

➜  ~ lsof +d ~ | grep vim
vim     16950 root  cwd    DIR  253,0     4096 100663393 /root
vim     16950 root    4u   REG  253,0    12288 101290376 /root/.anaconda-ks.cfg.swp


其中第四行是 FD (File Description),cwd 代表当前工作目录,r,w,u 分别代表打开文件读,写,读写。更多的可以 man lsof 找到

pidof:根据名字找到程序的 PID

➜  ~ pidof vim
16950

Share

You may also like...

发表评论