-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path0440processcontrol.html
2505 lines (2504 loc) · 223 KB
/
0440processcontrol.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="Author" content="VBird, 鸟哥">
<meta name="Description" content="进程管理与 SELinux 初探">
<title>鸟哥的 Linux 私房菜 -- 第十六章、进程管理与 SELinux 初探</title>
<style type="text/css">
</style>
<link href="./vbird_files/style_2013.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="tablearea">
<div class="mainarea">
<div class="block1">
<!-- 本文的档头部分 -->
<h1>第十六章、进程管理与 SELinux 初探</h1>
<div style="text-align:right">
<span class="text_history">最近更新日期:2016/10/24</span>
</div>
<!-- 本文的档头部分 -->
<div class="abstract">
<p>一个程序被加载到内存当中运作,那么在内存内的那个数据就被称为进程(process)。进程是操作系统上非常重要的概念,
所有系统上面跑的数据都会以进程的型态存在。那么系统的进程有哪些状态?不同的状态会如何影响系统的运作?
进程之间是否可以互相控管等等的,这些都是我们所必须要知道的项目。
另外与进程有关的还有 SELinux 这个加强文件访问安全性的咚咚,也必须要做个了解呢!</p>
</div>
<!-- 本文的链接区部分 -->
<div class="links">
<ul>
<li><a href="0440processcontrol.html#whatis">16.1 什么是进程 (Process)</a>
<ul>
<li><a href="0440processcontrol.html#whatis_program_process">16.1.1 进程与程序 (process & program)</a>:
<a href="0440processcontrol.html#parent_pid">子进程与父进程</a>, <a href="0440processcontrol.html#fork_and_exec">fork-and-exec</a>,
<a href="0440processcontrol.html#the_daemon">系统服务</a></li>
<li><a href="0440processcontrol.html#whatis_milti_task">16.1.2 Linux 的多人多任务环境</a></li>
</ul></li>
<li><a href="0440processcontrol.html#background">16.2 工作管理 (job control)</a>
<ul>
<li><a href="0440processcontrol.html#background_what">16.2.1 什么是工作管理</a></li>
<li><a href="0440processcontrol.html#background_run">16.2.2 job control 的管理</a>:<a href="0440processcontrol.html#the_and">&</a>, <a href="0440processcontrol.html#ctrl_z">[ctrl]-z</a>,
<a href="0440processcontrol.html#jobs">jobs</a>, <a href="0440processcontrol.html#fg">fg</a>, <a href="0440processcontrol.html#bg">bg</a>, <a href="0440processcontrol.html#killjobs">kill</a></li>
<li><a href="0440processcontrol.html#background_term">16.2.3 脱机管理问题</a>: <a href="0440processcontrol.html#nohup">nohup</a></li>
</ul></li>
<li><a href="0440processcontrol.html#process">16.3 进程管理</a>
<ul>
<li><a href="0440processcontrol.html#process_1">16.3.1 进程的观察</a>: <a href="0440processcontrol.html#ps">ps</a> (<a href="0440processcontrol.html#ps_l">ps -l</a>,
<a href="0440processcontrol.html#ps_aux">ps aux</a>, <a href="0440processcontrol.html#zombie">zombie</a>), <a href="0440processcontrol.html#topm">top</a>,
<a href="0440processcontrol.html#pstree">pstree</a></li>
<li><a href="0440processcontrol.html#process_2">16.3.2 进程的管理</a>: <a href="0440processcontrol.html#signal">signal</a>, <a href="0440processcontrol.html#kill">kill</a>,
<a href="0440processcontrol.html#killall">killall</a></li>
<li><a href="0440processcontrol.html#priority">16.3.3 关于进程的运行顺序</a>: <a href="0440processcontrol.html#pri">priority</a>,
<a href="0440processcontrol.html#nice">nice</a>, <a href="0440processcontrol.html#renice">renice</a></li>
<li><a href="0440processcontrol.html#process_3">16.3.4 系统资源的观察</a>: <a href="0440processcontrol.html#free">free</a>,
<a href="0440processcontrol.html#uname">uname</a>, <a href="0440processcontrol.html#uptime">uptime</a>,
<a href="0440processcontrol.html#netstat">netstat</a>, <a href="0440processcontrol.html#dmesg">dmesg</a>, <a href="0440processcontrol.html#vmstat">vmstat</a></li>
</ul></li>
<li><a href="0440processcontrol.html#special">16.4 特殊文件与进程</a>
<ul>
<li><a href="0440processcontrol.html#suid_sgid">16.4.1 具有 SUID/SGID 权限的指令运行状态</a></li>
<li><a href="0440processcontrol.html#proc">16.4.2 /proc/* 代表的意义</a></li>
<li><a href="0440processcontrol.html#ofile">16.4.3 查找已开启文件或已运行进程开启之文件</a>: <a href="0440processcontrol.html#fuser">fuser</a>,
<a href="0440processcontrol.html#lsof">lsof</a>, <a href="0440processcontrol.html#pidof">pidof</a></li>
</ul></li>
<li><a href="0440processcontrol.html#selinux">16.5 SELinux 初探</a>
<ul>
<li><a href="0440processcontrol.html#selinux_what">16.5.1 什么是 SELinux</a>: <a href="0440processcontrol.html#history">目标</a>, <a href="0440processcontrol.html#dac">DAC</a>,
<a href="0440processcontrol.html#mac">MAC</a></li>
<li><a href="0440processcontrol.html#selinux_run">16.5.2 SELinux 的运作模式</a>: <a href="0440processcontrol.html#selinux_com">组件</a>, <a href="0440processcontrol.html#context">安全性本文</a>,
<a href="0440processcontrol.html#domain_type">domain/type</a></li>
<li><a href="0440processcontrol.html#selinux_get">16.5.3 SELinux 三种模式的启动、关闭与观察</a>: <a href="0440processcontrol.html#getenforce">getenforce</a>,
<a href="0440processcontrol.html#sestatus">sestatus</a>, <a href="0440processcontrol.html#on_off">启动与关闭</a>, <a href="0440processcontrol.html#setenforce">setenforce</a></li>
<li><a href="0440processcontrol.html#selinux_policy">16.5.4 SELinux 政策内的规则管理</a>:
<a href="0440processcontrol.html#getsebool">getsebool</a>,
<a href="0440processcontrol.html#seinfo">seinfo</a>,
<a href="0440processcontrol.html#sesearch">sesearch</a>,
<a href="0440processcontrol.html#setsebool">setsebool</a></li>
<li><a href="0440processcontrol.html#selinux_chcon">16.5.5 SELinux 安全本文的修改</a>:
<a href="0440processcontrol.html#chcon">chcon</a>,
<a href="0440processcontrol.html#restorecon">restorecon</a>,
<a href="0440processcontrol.html#semanage">semanage</a></li>
<li><a href="0440processcontrol.html#selinux_ftp">16.5.6 一个网络服务案例及注册表协助</a>:
<a href="0440processcontrol.html#setroubleshoot">所需服务</a>,
<a href="0440processcontrol.html#selinux_ftp_how">FTP 实例</a>,
<a href="0440processcontrol.html#selinux_ftp_type">匿名者范例</a>,
<a href="0440processcontrol.html#ftp_home">一般用户家目录</a>,
<a href="0440processcontrol.html#ftp_other">非正规目录</a>,
<a href="0440processcontrol.html#ftp_other">非正规 port</a></li>
</ul></li>
<li><a href="0440processcontrol.html#hint">16.6 重点回顾</a></li>
<li><a href="0440processcontrol.html#ex">16.7 本章习题</a></li>
<li><a href="0440processcontrol.html#reference">16.8 参考数据与延伸阅读</a></li>
</ul>
</div>
</div>
<!-- 本文的正式部分 -->
<a id="whatis"></a>
<div class="block1">
<h2>16.1 什么是进程 (process)</h2>
<p>由前面一连几个章节的数据看来,我们一直强调在 Linux 底下所有的指令与你能够进行的动作都与权限有关,
而系统如何判定你的权限呢?当然就是<a href="0410accountmanager.html">第十三章帐号管理</a>当中提到的
UID/GID 的相关概念,以及文件的属性相关性啰!再进一步来解释,你现在大概知道,在 Linux
系统当中:『<span class="text_import2">触发任何一个事件时,系统都会将他定义成为一个进程,并且给予这个进程一个
ID ,称为 PID,同时依据启发这个进程的用户与相关属性关系,给予这个 PID 一组有效的权限设置。</span>』
从此以后,这个 PID 能够在系统上面进行的动作,就与这个 PID 的权限有关了!</p>
<p>看这个定义似乎没有什么很奇怪的地方,不过,您得要了解什么叫做『触发事件』才行啊!
我们在什么情况下会触发一个事件?而同一个事件可否被触发多次?呵呵!来了解了解先!</p>
<a id="whatis_program_process"></a>
<div class="block2"><div class="gototop"><a href="0440processcontrol.html#top">Top</a></div>
<h2>16.1.1 进程与程序 (process & program)</h2>
<p>我们如何产生一个进程呢?其实很简单啦,就是『运行一个程序或指令』就可以触发一个事件而取得一个
PID 啰!我们说过,系统应该是仅认识 binary file 的,那么当我们要让系统工作的时候,当然就是需要启动一个
binary file 啰,那个 binary file 就是程序 (program) 啦!</p>
<p>那我们知道,每个程序都有三组人马的权限,每组人马都具有 r/w/x 的权限,所以:『不同的用户身份运行这个
program 时,系统给予的权限也都不相同!』举例来说,我们可以利用 touch 来创建一个空的文件,当 root 运行这个 touch
指令时,他取得的是 UID/GID = 0/0 的权限,而当 dmtsai (UID/GID=501/501)
运行这个 touch 时,他的权限就跟 root 不同啦!我们将这个概念绘制成图标来瞧瞧如下:</p>
<a id="fig16.1.1"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/process_1.gif" alt="程序被加载成为进程以及相关数据的示意图" title="程序被加载成为进程以及相关数据的示意图" style="border: 1px solid black; padding: 10px "></div>
<div style="text-align: center;">图16.1.1、程序被加载成为进程以及相关数据的示意图</div>
<p>如上图所示,程序一般是放置在实体磁盘中,然后透过用户的运行来触发。触发后会加载到内存中成为一个个体,那就是进程。
为了操作系统可管理这个进程,因此进程有给予运行者的权限/属性等参数,并包括程序所需要的脚本与数据或文件数据等,
最后再给予一个 PID 。系统就是透过这个 PID 来判断该 process 是否具有权限进行工作的!他是很重要的哩!</p>
<p>举个更常见的例子,我们要操作系统的时候,通常是利用连接程序或者直接在主机前面登录,然后取得我们的
shell 对吧!那么,我们的 shell 是 bash 对吧,这个 bash 在 /bin/bash 对吧,那么同时间的每个人登录都是运行
/bin/bash 对吧!不过,每个人取得的权限就是不同!也就是说,我们可以这样看:</p>
<a id="fig16.1.2"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/program_process.gif" alt="程序与进程之间的差异" title="程序与进程之间的差异" style="border: 1px solid black; padding: 10px "></div>
<div style="text-align: center;">图16.1.2、程序与进程之间的差异</div>
<p>也就是说,当我们登录并运行 bash 时,系统已经给我们一个 PID 了,这个 PID 就是依据登录者的 UID/GID
(/etc/passwd) 来的啦~以上面的图 16.1.2 配合图 16.1.1 来做说明的话,我们知道 /bin/bash 是一个程序 (program),当 dmtsai
登录后,他取得一个 PID 号码为 2234 的进程,这个进程的 User/Group 都是 dmtsai
,而当这个程序进行其他作业时,例如上面提到的 touch 这个指令时,
那么由这个进程<span class="text_import2">衍生出来的其他进程在一般状态下,也会沿用这个进程的相关权限</span>的!</p>
<p>让我们将程序与进程作个总结:</p>
<ul class="text_import2">
<li>程序 (program):通常为 binary program ,放置在保存媒体中 (如硬盘、光盘、软碟、磁带等),
为实体文件的型态存在;<br><br></li>
<li>进程 (process):程序被触发后,运行者的权限与属性、程序的代码与所需数据等都会被加载内存中,
操作系统并给予这个内存内的单元一个识别码 (PID),可以说,进程就是一个正在运作中的程序。</li>
</ul>
<a id="parent_pid"></a>
<ul class="toplist"><li>子进程与父进程:</li></ul>
<p>在上面的说明里面,我们有提到所谓的『衍生出来的进程』,那是个啥咚咚?这样说好了,当我们登录系统后,会取得一个
bash 的 shell ,然后,我们用这个 bash 提供的接口去运行另一个指令,例如 /usr/bin/passwd 或者是 touch
等等,那些另外运行的指令也会被触发成为 PID ,呵呵!那个后来运行指令才产生的 PID 就是『子进程』了,而在我们原本的 bash
环境下,就称为『父进程』了!借用我们在<a href="0320bash.html#export">第十章 Bash 谈到的 export</a>
所用的图标好了:</p>
<a id="fig16.1.3"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/ppid.gif" alt="进程相关系之示意图" title="进程相关系之示意图" style="border: 1px solid black; padding: 10px "></div>
<div style="text-align: center;">图16.1.3、进程相关系之示意图</div>
<p>所以你必须要知道,程序彼此之间是有相关性的!以上面的图标来看,连续运行两个 bash 后,第二个 bash
的父进程就是前一个 bash。因为每个进程都有一个 PID ,那某个进程的父进程该如何判断?就透过 Parent PID (PPID)
来判断即可。此外,由第十章的 export 内容我们也探讨过环境变量的继承问题,子进程可以取得父进程的环境变量啦!
让我们来进行底下的练习,以了解什么是子进程/父进程。</p>
<table class="exam" style="width: 90%"><tbody><tr><td>
例题:<div>
请在目前的 bash 环境下,再触发一次 bash ,并以『 ps -l 』这个指令观察进程相关的输出信息。
</div>
答:<div>
直接运行 bash ,会进入到子进程的环境中,然后输入 ps -l 后,出现:
<pre style="font-size: 10pt">F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 <span style="text-decoration: underline">13928</span> 13927 0 80 0 - 29038 wait pts/0 00:00:00 bash
0 S 1000 13970 <span style="text-decoration: underline">13928</span> 1 80 0 - 29033 wait pts/0 00:00:00 bash
0 R 1000 14000 13970 0 80 0 - 30319 - pts/0 00:00:00 ps</pre>
有看到那个 PID 与 PPID 吗?第一个 bash 的 PID 与第二个 bash 的 PPID 都是 13928 啊,
因为第二个 bash 是来自于第一个所产生的嘛!另外,每部主机的程序启动状态都不一样,
所以在你的系统上面看到的 PID 与我这里的显示一定不同!那是正常的!详细的 <a href="0440processcontrol.html#ps">ps</a> 指令我们会在本章稍后介绍,
这里你只要知道 ps -l 可以查阅到相关的进程信息即可。
</div>
</td></tr></tbody></table>
<p>很多朋友常常会发现:『咦!明明我将有问题的进程关闭了,怎么过一阵子他又自动的产生?
而且新产生的那个进程的 PID 与原先的还不一样,这是怎么回事呢?』不要怀疑,如果不是 <a href="0430cron.html">crontab 工作调度</a>的影响,肯定有一支父进程存在,所以你杀掉子进程后,
父进程就会主动再生一支!那怎么办?正所谓这:『擒贼先擒王』,找出那支父进程,然后将他删除就对啦!</p>
<a id="fork_and_exec"></a>
<ul class="toplist"><li>fork and exec:进程调用的流程</li></ul>
<p>其实子进程与父进程之间的关系还挺复杂的,最大的复杂点在于进程互相之间的调用。<span class="text_import2">在 Linux 的进程调用通常称为 fork-and-exec 的流程
(<a href="0440processcontrol.html#ps1">注1</a>)!进程都会借由父进程以复制 (fork) 的方式产生一个一模一样的子进程,
然后被复制出来的子进程再以 exec 的方式来运行实际要进行的程序,最终就成为一个子进程的存在</span>。
整个流程有点像底下这张图:</p>
<a id="fig16.1.4"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/fork-and-exec.gif" alt="进程使用 fork and exec 调用的情况示意图" title="进程使用 fork and exec 调用的情况示意图" style="border: 1px solid black; padding: 10px "></div>
<div style="text-align: center;">图16.1.4、进程使用 fork and exec 调用的情况示意图</div>
<p>(1)系统先以 fork 的方式复制一个与父进程相同的暂存进程,这个进程与父进程唯一的差别就是 PID 不同!
但是这个暂存进程还会多一个 PPID 的参数,PPID 如前所述,就是父进程的进程识别码啦!然后(2)暂存进程开始以 exec
的方式加载实际要运行的程序,以上述图标来讲,新的程序名称为 qqq ,最终子进程的代码就会变成 qqq 了!
这样了解乎!</p>
<a id="the_daemon"></a>
<ul class="toplist"><li>系统或网络服务:常驻在内存的进程</li></ul>
<p>如果就我们之前学到的一些指令数据来看,其实我们下达的指令都很简单,包括用 ls 显示文件啊、用 touch
创建文件啊、rm/mkdir/cp/mv 等指令管理文件啊、chmod/chown/passwd 等等的指令来管理权限等等的,不过,
这些指令都是运行完就结束了。也就是说,该项指令被触发后所产生的 PID 很快就会终止呢!
那有没有一直在运行的进程啊?当然有啊!而且多的是呢!</p>
<p>举个简单的例子来说好了,我们知道系统每分钟都会去扫瞄 /etc/crontab 以及相关的设置档,
来进行工作调度吧?那么那个工作调度是谁负责的?当然不是鸟哥啊!
呵呵!是 crond 这个程序所管理的,<span class="text_import2">我们将他启动在背景当中一直持续不断的运作,
套句鸟哥以前 DOS 年代常常说的一句话,那就是『常驻在内存当中的进程』啦!</span></p>
<p>常驻在内存当中的进程通常都是负责一些系统所提供的功能以服务用户各项任务,因此<span class="text_import2">这些常驻程序就会被我们称为:服务 (daemon)</span>。系统的服务非常的多,
不过主要大致分成系统本身所需要的服务,例如刚刚提到的 crond 及
atd ,还有 rsyslogd 等等的。还有一些则是负责网络连接的服务,例如 Apache, named, postfix,
vsftpd... 等等的。这些网络服务比较有趣的地方,在于这些程序被运行后,他会启动一个可以负责网络监听的端口口
(port) ,以提供外部用户端 (client) 的连接要求。</p>
<fieldset class="vbirdface"><legend style="font-family: serif; font-size:12pt; color: darkblue;">Tips</legend><img src="./vbird_files/vbird_face.gif" alt="鸟哥的图标" title="鸟哥的图标" style="float: right;"> 以 crontab 来说,他的主要运行程序名称应该是 cron 或 at 才对,为啥要加个 d 在后面?而成为 crond, atd 呢?就是因为 Linux 希望我们可以简单的判断该程序是否为 daemon,
所以,一般 daemon 类型的程序都会加上 d 在文件名后头~包括服务器篇我们会看到的 httpd, vsftpd 等等都是 ^_^。
</fieldset><br> </div><br>
<a id="whatis_milti_task"></a>
<div class="block2"><div class="gototop"><a href="0440processcontrol.html#top">Top</a></div>
<h2>16.1.2 Linux 的多人多任务环境</h2>
<p>我们现在知道了,其实在 Linux 底下运行一个指令时,系统会将相关的权限、属性、代码与数据等均加载内存,
并给予这个单元一个进程识别码 (PID),最终该指令可以进行的任务则与这个 PID
的权限有关。根据这个说明,我们就可以简单的了解,为什么 Linux 这么多用户,但是却每个人都可以拥有自己的环境了吧!^_^
!底下我们来谈谈 Linux 多人多任务环境的特色:</p>
<ul class="toplist"><li>多人环境:</li></ul>
<p>Linux 最棒的地方就在于他的多人多任务环境了!那么什么是『多人多任务』?在 Linux 系统上面具有多种不同的帐号,
每种帐号都有都有其特殊的权限,只有一个人具有至高无上的权力,那就是
root (系统管理员)。除了 root 之外,其他人都必须要受一些限制的!而每个人进入
Linux 的环境设置都可以随着每个人的喜好来设置 (还记得我们在<a href="0320bash.html">第十章 BASH</a>
提过的 ~/.bashrc 吧?对了!就是那个光!)!现在知道为什么了吧?因为每个人登录后取得的 shell 的 PID
不同嘛!</p>
<ul class="toplist"><li>多任务行为:</li></ul>
<p>我们在<a href="0105computers.html">第零章</a>谈到 CPU 的速度,目前的 CPU 速度可高达几个 GHz。
这代表 CPU 每秒钟可以运作 10<sup>9</sup> 这么多次指令。我们的 Linux 可以让 CPU 在各个工作间进行切换,
也就是说,其实每个工作都仅占去 CPU 的几个指令次数,所以 CPU 每秒就能够在各个进程之间进行切换啦!
谁叫 CPU 可以在一秒钟进行这么多次的指令运作。</p>
<p>CPU 切换进程的工作,与这些工作进入到 CPU 运作的调度 (CPU 调度,非 crontab 调度) 会影响到系统的整体性能!
目前 Linux 使用的多任务切换行为是非常棒的一个机制,几乎可以将 PC 的性能整个压榨出来!
由于性能非常好,因此当多人同时登录系统时,其实会感受到整部主机好像就为了你存在一般!
这就是多人多任务的环境啦!(<a href="0440processcontrol.html#ps2">注2</a>)</p>
<ul class="toplist"><li>多重登录环境的七个基本终端窗口:</li></ul>
<p>在 Linux 当中,缺省提供了六个文本界面登录窗口,以及一个图形界面,你可以使用
[Alt]+[F1].....[F7] 来切换不同的终端机界面,而且每个终端机界面的登录者还可以不同人!
很炫吧!这个东西可就很有用啦!尤其是在某个进程死掉的时候!</p>
<p>其实,这也是多任务环境下所产生的一个情况啦!我们的 Linux
缺省会启动六个终端机登录环境的程序,所以我们就会有六个终端机接口。
您也可以减少啊!就是减少启动的终端机程序就好了。
未来我们在<a href="0510osloader.html">开机管理流程 (第十九章)</a> 会再仔细的介绍的!</p>
<ul class="toplist"><li>特殊的进程管理行为:</li></ul>
<p>以前的鸟哥笨笨的,总是以为使用 Windows 98 就可以啦!后来,因为工作的关系,需要使用 Unix
系统,想说我只要在工作机前面就好,才不要跑来跑去的到 Unix 工作站前面去呢!所以就使用 Windows 连到我的
Unix 工作站工作!好死不死,我一个进程跑下来要 2~3 天,唉~偏偏常常到了第 2.5 天的时候, Windows 98
就给他挂点去!当初真的是给他怕死了~</p>
<p>后来因为换了新电脑,用了随机版的 Windows 2000 ,呵呵,这东西真不错 (指对单人而言) ,在当机的时候,
他可以仅将错误的进程踢掉,而不干扰其他的进程进行,呵呵!
从此以后,就不用担心会当机连连啰!不过,2000 毕竟还不够好,因为有的时候还是会死当!</p>
<p>那么 Linux 会有这样的问题吗?老实说, Linux 几乎可以说绝对不会当机的!因为他可以在任何时候,
将某个被困住的进程杀掉,然后再重新运行该进程而不用重新开机!够炫吧!那么如果我在
Linux 下以文本界面登录,在屏幕当中显示错误消息后就挂了~动都不能动,该如何是好!?
这个时候那缺省的七个窗口就帮上忙啦!你可以随意的再按
[Alt]+[F1].....[F7] 来切换到其他的终端机界面,然后以 <a href="0440processcontrol.html#ps">ps -aux</a> 找出刚刚的错误进程,然后给他
<a href="0440processcontrol.html#kill">kill</a> 一下,哈哈,回到刚刚的终端机界面!恩~棒!又回复正常啰!</p>
<p>为什么可以这样做呢?我们刚刚不是提过吗?每个进程之间可能是独立的,也可能有相依性,
只要到独立的进程当中,删除有问题的那个进程,当然他就可以被系统移除掉啦!^_^</p>
<ul class="toplist"><li>bash 环境下的工作管理 (job control)</li></ul>
<p>我们在上一个小节有提到所谓的『父进程、子进程』的关系,那我们登录 bash 之后,
就是取得一个名为 bash 的 PID 了,而在这个环境底下所运行的其他指令,
就几乎都是所谓的子进程了。那么,在这个单一的 bash 接口下,我可不可以进行多个工作啊?
当然可以啦!可以『同时』进行喔!举例来说,我可以这样做:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">cp file1 file2 &</span>
</pre></td></tr></tbody></table>
<p>在这一串指令中,重点在那个 & 的功能,他表示将 file1 这个文件复制为 file2 ,且放置于背景中运行,
也就是说运行这一个命令之后,在这一个终端接口仍然可以做其他的工作!而当这一个指令 (cp file1 file2)
运行完毕之后,系统将会在你的终端接口显示完成的消息!很便利喔!</p>
<ul class="toplist"><li>多人多任务的系统资源分配问题考虑:</li></ul>
<p>多人多任务确实有很多的好处,但其实也有管理上的困扰,因为用户越来越多,
将导致你管理上的困扰哩!另外,由于用户日盛,当用户达到一定的人数后,
通常你的机器便需要升级了,因为 CPU 的运算与 RAM 的大小可能就会不敷使用!</p>
<p>举个例子来说,鸟哥之前的网站管理的有点不太好,因为使用了一个很复杂的人数统计程序,
这个程序会一直去取用 MySQL 数据库的数据,偏偏因为流量大,造成 MySQL 很忙碌。
在这样的情况下,当鸟哥要登录去写网页数据,或者要去使用讨论区的资源时,
哇!慢的很!简直就是『龟速』啊!后来终于将这个程序停止不用了,
以自己写的一个小程序来取代,呵呵!这样才让 CPU 的负载 (loading) 整个降下来~
用起来顺畅多了! ^_^</p>
<br></div><br>
</div>
<a id="background"></a>
<div class="block1">
<h2>16.2 工作管理 (job control)</h2>
<p>这个工作管理 (job control) 是用在 bash 环境下的,也就是说:『<span class="text_import2">当我们登录系统取得 bash shell
之后,在<span style="text-decoration: underline">单一终端机接口</span>下同时进行多个工作的行为管理</span> 』。举例来说,我们在登录 bash 后,
想要一边复制文件、一边进行数据搜索、一边进行编译,还可以一边进行 vim 程序撰写!
当然我们可以重复登录那六个文本接口的终端机环境中,不过,能不能在一个 bash 内达成?
当然可以啊!就是使用 job control 啦! ^_^</p>
<a id="background_what"></a>
<div class="block2"><div class="gototop"><a href="0440processcontrol.html#top">Top</a></div>
<h2>16.2.1 什么是工作管理?</h2>
<p>从上面的说明当中,你应该要了解的是:『<span class="text_import2">进行工作管理的行为中,
其实每个工作都是目前 bash 的子进程,亦即彼此之间是有相关性的。
我们无法以 job control 的方式由 tty1 的环境去管理 tty2 的 bash !</span>』
这个概念请你得先创建起来,后续的范例介绍之后,你就会清楚的了解啰!</p>
<p>或许你会觉得很奇怪啊,既然我可以在六个终端接口登录,那何必使用 job control 呢?
真是脱裤子放屁,多此一举啊!不要忘记了呢,我们可以在 <a href="0410accountmanager.html#limits">/etc/security/limits.conf (第十三章)</a>
里面设置用户同时可以登录的连接数,在这样的情况下,某些用户可能仅能以一个连接来工作呢!
所以啰,你就得要了解一下这种工作管理的模式了!此外,这个章节内容也会牵涉到很多的数据流重导向,所以,如果忘记的话,
务必回到<a href="0320bash.html">第十章 BASH Shell</a> 看一看喔!</p>
<p>由于假设我们只有一个终端接口,因此在<span class="text_import2">可以出现提示字符让你操作的环境就称为前景
(foreground),至于其他工作就可以让你放入背景 (background) 去暂停或运作。</span>要注意的是,放入背景的工作想要运作时,
他必须不能够与用户交互。举例来说, vim 绝对不可能在背景里面运行 (running) 的!因为你没有输入数据他就不会跑啊!
而且<span class="text_import2">放入背景的工作是不可以使用 [ctrl]+c 来终止的</span>!</p>
<p>总之,要进行 bash 的 job control 必须要注意到的限制是:</p>
<ul class="text_import2">
<li>这些工作所触发的进程必须来自于你 shell 的子进程(只管理自己的 bash);</li>
<li>前景:你可以控制与下达指令的这个环境称为前景的工作 (foreground);</li>
<li>背景:可以自行运作的工作,你无法使用 [ctrl]+c 终止他,可使用 bg/fg 调用该工作;</li>
<li>背景中『运行』的进程不能等待 terminal/shell 的输入(input)</li></ul>
<p>接下来让我们实际来管理这些工作吧!</p>
<br></div><br>
<a id="background_run"></a>
<div class="block2"><div class="gototop"><a href="0440processcontrol.html#top">Top</a></div>
<h2>16.2.2 job control 的管理</h2>
<p>如前所述,bash 只能够管理自己的工作而不能管理其他 bash 的工作,所以即使你是 root 也不能够将别人的 bash
底下的 job 给他拿过来运行。此外,又分前景与背景,然后在背景里面的工作状态又可以分为『暂停 (stop)』与『运作中
(running)』。那实际进行 job 控制的指令有哪些?底下就来谈谈。</p>
<a id="the_and"></a>
<ul class="toplist"><li>直接将指令丢到背景中『运行』的 &</li></ul>
<p>如同前面提到的,我们在只有一个 bash 的环境下,如果想要同时进行多个工作,
那么可以将某些工作直接丢到背景环境当中,让我们可以继续操作前景的工作!那么如何将工作丢到背景中?
最简单的方法就是利用『 & 』这个玩意儿了!举个简单的例子,我们要将 /etc/ 整个备份成为
/tmp/etc.tar.gz 且不想要等待,那么可以这样做:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">tar -zpcf /tmp/etc.tar.gz /etc &</span>
[1] 14432 <span class="term_note"><== [job number] PID </span>
[root@study ~]# tar: Removing leading `/' from member names
<span class="term_say"># 在中括号内的号码为工作号码 (job number),该号码与 bash 的控制有关。
# 后续的 14432 则是这个工作在系统中的 PID。至于后续出现的数据是 tar 运行的数据流,
# 由于我们没有加上数据流重导向,所以会影响画面!不过不会影响前景的操作喔!</span>
</pre></td></tr></tbody></table>
<p>仔细的瞧一瞧,我在输入一个指令后,在该指令的最后面加上一个『 & 』代表将该指令丢到背景中,
此时 bash 会给予这个指令一个『工作号码(job number)』,就是那个 [1] 啦!至于后面那个 14432
则是该指令所触发的『 PID 』了!而且,有趣的是,我们可以继续操作 bash 呢!很不赖吧!
不过,那么丢到背景中的工作什么时候完成?完成的时候会显示什么?如果你输入几个指令后,突然出现这个数据:</p>
<table class="term"><tbody><tr><td class="term"><pre>[1]+ Done tar -zpcf /tmp/etc.tar.gz /etc
</pre></td></tr></tbody></table>
<p>就代表 [1] 这个工作已经完成 (Done) ,该工作的指令则是接在后面那一串指令列。
这样了解了吧!另外,这个 & 代表:『将工作丢到背景中去运行』喔!
注意到那个『运行』的字眼!此外,这样的情况最大的好处是:
<span class="text_import2">不怕被 [ctrl]+c 中断</span>的啦!
此外,将工作丢到背景当中要特别注意数据的流向喔!包括上面的消息就有出现错误消息,导致我的前景被影响。
虽然只要按下 [enter] 就会出现提示字符。但如果我将刚刚那个指令改成:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">tar -zpcvf /tmp/etc.tar.gz /etc &</span>
</pre></td></tr></tbody></table>
<p>情况会怎样?在背景当中运行的指令,如果有 stdout 及 stderr 时,他的数据依旧是输出到屏幕上面的,
所以,我们会无法看到提示字符,当然也就无法完好的掌握前景工作。同时由于是背景工作的 tar ,
此时你怎么按下 [ctrl]+c 也无法停止屏幕被搞的花花绿绿的!所以啰,最佳的状况就是利用数据流重导向,
将输出数据发送至某个文件中。举例来说,我可以这样做:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">tar -zpcvf /tmp/etc.tar.gz /etc > /tmp/log.txt 2>&1 &</span>
[1] 14547
[root@study ~]#
</pre></td></tr></tbody></table>
<p>呵呵!如此一来,输出的信息都给他发送到 /tmp/log.txt 当中,当然就不会影响到我们前景的作业了。
这样说,您应该可以更清楚数据流重导向的重要性了吧!^_^</p>
<fieldset class="vbirdface"><legend style="font-family: serif; font-size:12pt; color: darkblue;">Tips</legend><img src="./vbird_files/vbird_face.gif" alt="鸟哥的图标" title="鸟哥的图标" style="float: right;"> 工作号码 (job number) 只与你这个 bash 环境有关,但是他既然是个指令触发的咚咚,所以当然一定是一个进程,
因此你会观察到有 job number 也搭配一个 PID !
</fieldset><br>
<a id="ctrl_z"></a>
<ul class="toplist"><li>将『目前』的工作丢到背景中『暂停』:[ctrl]-z</li></ul>
<p>想个情况:如果我正在使用 vim ,却发现我有个文件不知道放在哪里,需要到 bash
环境下进行搜索,此时是否要结束 vim 呢?呵呵!当然不需要啊!只要暂时将 vim 给他丢到背景当中等待即可。
例如以下的案例:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">vim ~/.bashrc</span>
<span class="term_say"># 在 vim 的一般模式下,按下 [ctrl]-z 这两个按键</span>
[1]+ Stopped vim ~/.bashrc
[root@study ~]# <span class="term_note"><==顺利取得了前景的操控权!</span>
[root@study ~]# <span class="term_command">find / -print</span>
<span class="term_say">....(输出省略)....
# 此时屏幕会非常的忙碌!因为屏幕上会显示所有的文件名。请按下 [ctrl]-z 暂停</span>
[2]+ Stopped find / -print
</pre></td></tr></tbody></table>
<p>在 vim 的一般模式下,按下 [ctrl] 及 z 这两个按键,屏幕上会出现 [1] ,表示这是第一个工作,
而<span class="text_import2">那个 + 代表最近一个被丢进背景的工作,且目前在背景下缺省会被取用的那个工作
(与 fg 这个指令有关 )!而那个 Stopped 则代表目前这个工作的状态。在缺省的情况下,使用 [ctrl]-z
丢到背景当中的工作都是『暂停』的状态喔!</span></p>
<a id="jobs"></a>
<ul class="toplist"><li>观察目前的背景工作状态: jobs</li></ul>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">jobs [-lrs]</span>
<span class="term_say">选项与参数:
-l :除了列出 job number 与指令串之外,同时列出 PID 的号码;
-r :仅列出正在背景 run 的工作;
-s :仅列出正在背景当中暂停 (stop) 的工作。</span>
<span class="term_hd">范例一:观察目前的 bash 当中,所有的工作,与对应的 PID</span>
[root@study ~]# <span class="term_command">jobs -l</span>
[1]- 14566 Stopped vim ~/.bashrc
[2]+ 14567 Stopped find / -print
</pre></td></tr></tbody></table>
<p>如果想要知道目前有多少的工作在背景当中,就用 jobs 这个指令吧!一般来说,直接下达 jobs 即可!
不过,如果你还想要知道该 job number 的 PID 号码,可以加上 -l 这个参数啦!
在输出的信息当中,例如上表,仔细看到那个 + - 号喔!那个 + 代表缺省的取用工作。
所以说:『<span class="text_import2">目前我有两个工作在背景当中,两个工作都是暂停的,
而如果我仅输入 fg 时,那么那个 [2] 会被拿到前景当中来处理</span>』!</p>
<p><span class="text_import2">其实 + 代表最近被放到背景的工作号码, - 代表最近最后第二个被放置到背景中的工作号码。</span>
而超过最后第三个以后的工作,就不会有 +/- 符号存在了!</p>
<a id="fg"></a>
<ul class="toplist"><li>将背景工作拿到前景来处理:fg</li></ul>
<p>刚刚提到的都是将工作丢到背景当中去运行的,那么有没有可以将背景工作拿到前景来处理的?
有啊!就是那个 fg (foreground) 啦!举例来说,我们想要将上头范例当中的工作拿出来处理时:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">fg %jobnumber</span>
<span class="term_say">选项与参数:
%jobnumber :jobnumber 为工作号码(数字)。注意,那个 % 是可有可无的!</span>
<span class="term_hd">范例一:先以 jobs 观察工作,再将工作取出:</span>
[root@study ~]# <span class="term_command">jobs -l</span>
[1]- 14566 Stopped vim ~/.bashrc
[2]+ 14567 Stopped find / -print
[root@study ~]# <span class="term_command">fg </span> <span class="term_note"><==缺省取出那个 + 的工作,亦即 [2]。立即按下[ctrl]-z</span>
[root@study ~]# <span class="term_command">fg %1</span> <span class="term_note"><==直接规定取出的那个工作号码!再按下[ctrl]-z</span>
[root@study ~]# <span class="term_command">jobs -l</span>
[1]<span class="term_write">+</span> 14566 Stopped vim ~/.bashrc
[2]- 14567 Stopped find / -print
</pre></td></tr></tbody></table>
<p>经过 fg 指令就能够将背景工作拿到前景来处理啰!不过比较有趣的是最后一个显示的结果,我们会发现 + 出现在第一个工作后!
怎么会这样啊?这是因为你刚刚利用 fg %1 将第一号工作捉到前景后又放回背景,此时最后一个被放入背景的将变成 vi 那个指令动作,
所以当然 [1] 后面就会出现 + 了!了解乎!另外,如果输入『<span class="text_import2"> fg - </span>』
则代表将 - 号的那个工作号码拿出来,上面就是 [2]- 那个工作号码啦!</p>
<a id="bg"></a>
<ul class="toplist"><li>让工作在背景下的状态变成运作中: bg</li></ul>
<p>我们刚刚提到,那个 [ctrl]-z 可以将目前的工作丢到背景底下去『暂停』,
那么如何让一个工作在背景底下『 Run 』呢?我们可以在底下这个案例当中来测试!
注意喔!底下的测试要进行的快一点!^_^</p>
<table class="term"><tbody><tr><td class="term"><pre><span class="term_hd">范例一:一运行 find / -perm /7000 > /tmp/text.txt 后,立刻丢到背景去暂停!</span>
[root@study ~]# <span class="term_command">find / -perm /7000 > /tmp/text.txt</span>
<span class="term_say"># 此时,请立刻按下 [ctrl]-z 暂停!</span>
[3]+ Stopped find / -perm /7000 > /tmp/text.txt
<span class="term_hd">范例二:让该工作在背景下进行,并且观察他!!</span>
[root@study ~]# <span class="term_command">jobs ; bg %3 ; jobs</span>
[1] Stopped vim ~/.bashrc
[2]- Stopped find / -print
[3]+ <span class="term_write">Stopped</span> find / -perm /7000 > /tmp/text.txt
[3]+ find / -perm /7000 > /tmp/text.txt &
[1]- Stopped vim ~/.bashrc
[2]+ Stopped find / -print
[3] <span class="term_write">Running</span> find / -perm /7000 > /tmp/text.txt &
</pre></td></tr></tbody></table>
<p>看到哪里有差异吗?呼呼!没错!就是那个状态栏~以经由 Stopping 变成了 Running 啰!
看到差异点,嘿嘿!指令列最后方多了一个 & 的符号啰!
代表该工作被启动在背景当中了啦! ^_^</p>
<a id="killjobs"></a>
<ul class="toplist"><li>管理背景当中的工作: kill</li></ul>
<p>刚刚我们可以让一个已经在背景当中的工作继续工作,也可以让该工作以 fg 拿到前景来,
那么,如果想要将该工作直接移除呢?或者是将该工作重新启动呢?这个时候就得需要给予该工作一个信号
(signal) ,让他知道该怎么作才好啊!此时, kill 这个指令就派上用场啦!</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">kill -signal %jobnumber</span>
[root@study ~]# <span class="term_command">kill -l</span>
<span class="term_say">选项与参数:
-l :这个是 L 的小写,列出目前 kill 能够使用的信号 (signal) 有哪些?
signal :代表给予后面接的那个工作什么样的指示啰!用 man 7 signal 可知:
-1 :重新读取一次参数的设置档 (类似 reload);
-2 :代表与由键盘输入 [ctrl]-c 同样的动作;
-9 :立刻强制删除一个工作;
-15:以正常的进程方式终止一项工作。与 -9 是不一样的。</span>
<span class="term_hd">范例一:找出目前的 bash 环境下的背景工作,并将该工作『强制删除』。</span>
[root@study ~]# <span class="term_command">jobs</span>
[1]+ Stopped vim ~/.bashrc
[2] Stopped find / -print
[root@study ~]# <span class="term_command">kill -9 %2; jobs</span>
[1]+ Stopped vim ~/.bashrc
[2] <span class="term_write">Killed</span> find / -print
<span class="term_say"># 再过几秒你再下达 jobs 一次,就会发现 2 号工作不见了!因为被移除了!</span>
<span class="term_hd">范例二:找出目前的 bash 环境下的背景工作,并将该工作『正常终止』掉。</span>
[root@study ~]# <span class="term_command">jobs</span>
[1]+ Stopped vim ~/.bashrc
[root@study ~]# <span class="term_command">kill -SIGTERM %1</span>
<span class="term_say"># -SIGTERM 与 -15 是一样的!您可以使用 kill -l 来查阅!
# 不过在这个案例中, vim 的工作无法被结束喔!因为他无法透过 kill 正常终止的意思!</span>
</pre></td></tr></tbody></table>
<p>特别留意一下, <span class="text_import2">-9 这个 signal 通常是用在『强制删除一个不正常的工作』时所使用的,
-15 则是以正常步骤结束一项工作(15也是默认值)</span>,两者之间并不相同呦!举上面的例子来说,
我用 vim 的时候,不是会产生一个 .filename.swp 的文件吗?
那么,当使用 -15 这个 signal 时, vim 会尝试以正常的步骤来结束掉该 vi 的工作,
所以 .filename.swp 会主动的被移除。但若是使用 -9 这个 signal 时,由于该 vim 工作会被强制移除掉,因此,
.filename.swp 就会继续存在文件系统当中。这样您应该可以稍微分辨一下了吧?</p>
<p>不过,毕竟正常的作法中,你应该先使用 fg 来取回前景控制权,然后再离开 vim 才对~因此,以上面的范例二为例,其实 kill
确实无法使用 -15 正常的结束掉 vim 的动作喔!此时还是不建议使用 -9 啦!因为你知道如何正常结束该进程不是吗?
通常使用 -9 是因为某些程序你真的不知道怎么透过正常手段去终止他,这才用到 -9 的!</p>
<p>其实, kill 的妙用是很无穷的啦!他搭配 signal 所详列的信息 (用 man 7 signal 去查阅相关数据)
可以让您有效的管理工作与进程 (Process),此外,那个 killall 也是同样的用法!
至于常用的 signal 您至少需要了解 1, 9, 15 这三个 signal 的意义才好。
此外, signal 除了以数值来表示之外,也可以使用信号名称喔!
举例来说,上面的范例二就是一个例子啦!至于 signal number 与名称的对应,
呵呵,使用 kill -l 就知道啦(L的小写)!</p>
<p>另外, kill 后面接的数字缺省会是 PID ,如果想要管理 bash 的工作控制,就得要加上 %数字 了,
这点也得特别留意才行喔!</p>
<br></div><br>
<a id="background_term"></a>
<div class="block2"><div class="gototop"><a href="0440processcontrol.html#top">Top</a></div>
<h2>16.2.3 脱机管理问题</h2>
<p>要注意的是,我们在工作管理当中提到的『背景』指的是在终端机模式下可以避免 [ctrl]-c 中断的一个情境,
你可以说那个是 bash 的背景,并不是放到系统的背景去喔!所以,<span class="text_import2">工作管理的背景依旧与终端机有关</span>啦!
在这样的情况下,如果你是以远程连接方式连接到你的 Linux 主机,并且将工作以 & 的方式放到背景去,
请问,在工作尚未结束的情况下你脱机了,该工作还会继续进行吗?答案是『否』!不会继续进行,而是会被中断掉。</p>
<a id="nohup"></a>
<p>那怎么办?如果我的工作需要进行一大段时间,我又不能放置在背景底下,那该如何处理呢?
首先,你可以参考前一章的 <a href="0430cron.html#at">at</a> 来处理即可!因为 at 是将工作放置到系统背景,
而与终端机无关。如果不想要使用 at 的话,那你也可以尝试使用 nohup 这个指令来处理喔!这个 nohup
可以让你在脱机或注销系统后,还能够让工作继续进行。他的语法有点像这样:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">nohup [指令与参数] </span> <span class="term_note"><==在终端机前景中工作</span>
[root@study ~]# <span class="term_command">nohup [指令与参数] &</span> <span class="term_note"><==在终端机背景中工作</span>
</pre></td></tr></tbody></table>
<p>有够好简单的指令吧!上述指令需要注意的是, nohup 并不支持 bash 内置的指令,因此你的指令必须要是外部指令才行。
我们来尝试玩一下底下的任务吧!</p>
<table class="term"><tbody><tr><td class="term"><pre><span class="term_hd"># 1. 先编辑一支会『睡着 500 秒』的程序:</span>
[root@study ~]# <span class="term_command">vim sleep500.sh</span>
#!/bin/bash
/bin/sleep 500s
/bin/echo "I have slept 500 seconds."
<span class="term_hd"># 2. 丢到背景中去运行,并且立刻注销系统:</span>
[root@study ~]# <span class="term_command">chmod a+x sleep500.sh</span>
[root@study ~]# <span class="term_command">nohup ./sleep500.sh &</span>
[2] 14812
[root@study ~]# nohup: ignoring input and appending output to `nohup.out' <span class="term_note"><==会告知这个消息!</span>
[root@study ~]# <span class="term_command">exit</span>
</pre></td></tr></tbody></table>
<p>如果你再次登录的话,再使用 pstree 去查阅你的进程,会发现 sleep500.sh 还在运行中喔!并不会被中断掉!
这样了解意思了吗?由于我们的程序最后会输出一个消息,但是 nohup 与终端机其实无关了,
因此这个消息的输出就会被导向『 ~/nohup.out 』,所以你才会看到上述指令中,当你输入 nohup 后,
会出现那个提示消息啰。</p>
<p>如果你想要让在背景的工作在你注销后还能够继续的运行,那么使用 nohup 搭配 & 是不错的运作情境喔!
可以参考看看!</p>
<br></div>
</div>
<a id="process"></a>
<div class="block1">
<h2>16.3 进程管理</h2>
<p>本章一开始就提到所谓的『进程』的概念,包括进程的触发、子进程与父进程的相关性等等,
此外,还有那个『进程的相依性』以及所谓的『僵尸进程』等等需要说明的呢!为什么进程管理这么重要呢?这是因为:</p>
<ul>
<li>首先,本章一开始就谈到的,我们在操作系统时的各项工作其实都是经过某个 PID 来达成的 (包括你的 bash 环境),
因此,能不能进行某项工作,就与该进程的权限有关了。</li>
<li>再来,如果您的 Linux 系统是个很忙碌的系统,那么当整个系统资源快要被使用光时,
您是否能够找出最耗系统的那个进程,然后删除该进程,让系统恢复正常呢?</li>
<li>此外,如果由于某个程序写的不好,导致产生一个有问题的进程在内存当中,您又该如何找出他,然后将他移除呢?</li>
<li>如果同时有五六项工作在您的系统当中运作,但其中有一项工作才是最重要的,
该如何让那一项重要的工作被最优先运行呢?</li>
</ul>
<p>所以啰,一个称职的系统管理员,必须要熟悉进程的管理流程才行,否则当系统发生问题时,还真是很难解决问题呢!
底下我们会先介绍如何观察进程与进程的状态,然后再加以进程控制啰!</p>
<a id="process_1"></a>
<div class="block2"><div class="gototop"><a href="0440processcontrol.html#top">Top</a></div>
<h2>16.3.1 进程的观察</h2>
<p>既然进程这么重要,那么我们如何查阅系统上面正在运作当中的进程呢?很简单啊!
利用静态的 ps 或者是动态的 top,还能以 pstree 来查阅进程树之间的关系喔!</p>
<a id="ps"></a>
<ul class="toplist"><li>ps :将某个时间点的进程运作情况截取下来</li></ul>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">ps aux </span> <span class="term_note"><==观察系统所有的进程数据</span>
[root@study ~]# <span class="term_command">ps -lA </span> <span class="term_note"><==也是能够观察所有系统的数据</span>
[root@study ~]# <span class="term_command">ps axjf</span> <span class="term_note"><==连同部分进程树状态</span>
<span class="term_say">选项与参数:
-A :所有的 process 均显示出来,与 -e 具有同样的效用;
-a :不与 terminal 有关的所有 process ;
-u :有效用户 (effective user) 相关的 process ;
x :通常与 a 这个参数一起使用,可列出较完整信息。
输出格式规划:
l :较长、较详细的将该 PID 的的信息列出;
j :工作的格式 (jobs format)
-f :做一个更为完整的输出。</span>
</pre></td></tr></tbody></table>
<p>鸟哥个人认为 ps 这个指令的 man page 不是很好查阅,因为很多不同的 Unix 都使用这个 ps 来查阅进程状态,
为了要符合不同版本的需求,所以这个 man page 写的非常的庞大!因此,通常鸟哥都会建议你,直接背两个比较不同的选项,
<span class="text_import2">一个是只能查阅自己 bash 进程的『 ps -l 』一个则是可以查阅所有系统运作的进程『
ps aux 』</span>!注意,你没看错,是『 ps aux 』没有那个减号 (-) !先来看看关于自己 bash 进程状态的观察:</p>
<div class="illus">
<a id="ps_l"></a>
<ul><li>仅观察自己的 bash 相关进程: ps -l</li></ul>
<table class="term"><tbody><tr><td class="term"><pre><span class="term_hd">范例一:将目前属于您自己这次登录的 PID 与相关信息列示出来(只与自己的 bash 有关)</span>
[root@study ~]# <span class="term_command">ps -l</span>
<span style="text-decoration: underline">F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD</span>
4 S 0 14830 13970 0 80 0 - 52686 poll_s pts/0 00:00:00 sudo
4 S 0 14835 14830 0 80 0 - 50511 wait pts/0 00:00:00 su
<span style="text-decoration: underline">4 S 0 14836 14835 0 80 0 - 29035 wait pts/0 00:00:00 bash</span>
0 R 0 15011 14836 0 80 0 - 30319 - pts/0 00:00:00 ps
<span class="term_say"># 还记得鸟哥说过,非必要不要使用 root 直接登录吧?从这个 ps -l 的分析,你也可以发现,
# 鸟哥其实是使用 sudo 才转成 root 的身份~否则连测试机,鸟哥都是使用一般帐号登录的!</span>
</pre></td></tr></tbody></table>
<p>系统整体的进程运作是非常多的,但如果使用 ps -l 则仅列出与你的操作环境 (bash) 有关的进程而已,
亦即最上层的父进程会是你自己的 bash 而没有延伸到 systemd (后续会交待!) 这支进程去!那么 ps -l 秀出来的数据有哪些呢?
我们就来观察看看:</p>
<ul style="margin-left: 30px; list-style-type: square; color: #000000;">
<li style="color: #252525;">F:代表这个进程旗标 (process flags),说明这个进程的总结权限,常见号码有:<br>
<ul>
<li>若为 4 表示此进程的权限为 root ;</li>
<li>若为 1 则表示此子进程仅进行<a href="0440processcontrol.html#fork_and_exec">复制(fork)而没有实际运行(exec)</a>。</li>
</ul><br></li>
<li style="color: #252525;">S:代表这个进程的状态 (STAT),主要的状态有:<br>
<ul class="text_import2">
<li>R (Running):该程序正在运作中;</li>
<li>S (Sleep):该程序目前正在睡眠状态(idle),但可以被唤醒(signal)。</li>
<li>D :不可被唤醒的睡眠状态,通常这支程序可能在等待 I/O 的情况(ex>打印)</li>
<li>T :停止状态(stop),可能是在工作控制(背景暂停)或调试 (traced) 状态;</li>
<li>Z (Zombie):僵尸状态,进程已经终止但却无法被移除至内存外。</li>
</ul><br></li>
<li style="color: #252525;">UID/PID/PPID:代表『此进程被该 UID 所拥有/进程的 PID 号码/此进程的父进程 PID 号码』<br><br></li>
<li style="color: #252525;">C:代表 CPU 使用率,单位为百分比;<br><br></li>
<li style="color: #252525;">PRI/NI:Priority/Nice 的缩写,代表此进程被 CPU 所运行的优先级,数值越小代表该进程越快被
CPU 运行。详细的 PRI 与 NI 将在<a href="0440processcontrol.html#priority">下一小节</a>说明。<br><br></li>
<li style="color: #252525;">ADDR/SZ/WCHAN:都与内存有关,ADDR 是 kernel function,指出该进程在内存的哪个部分,如果是个 running
的进程,一般就会显示『 - 』 / SZ 代表此进程用掉多少内存 / WCHAN 表示目前进程是否运作中,同样的,
若为 - 表示正在运作中。<br><br></li>
<li style="color: #252525;">TTY:登录者的终端机位置,若为远程登录则使用动态终端接口 (pts/n);<br><br></li>
<li style="color: #252525;">TIME:使用掉的 CPU 时间,注意,是此进程实际花费 CPU 运作的时间,而不是系统时间;<br><br></li>
<li style="color: #252525;">CMD:就是 command 的缩写,造成此进程的触发程序之指令为何。</li>
</ul>
<p>所以你看到的 ps -l 输出消息中,他说明的是:『bash 的程序属于 UID 为 0 的用户,状态为睡眠 (sleep),
之所以为睡眠因为他触发了 ps (状态为 run) 之故。此进程的 PID 为 14836,优先运行顺序为 80 ,
下达 bash 所取得的终端接口为 pts/0 ,运作状态为等待 (wait) 。』这样已经够清楚了吧?
您自己尝试解析一下那么 ps 那一行代表的意义为何呢? ^_^</p>
<p>接下来让我们使用 ps 来观察一下系统内所有的进程状态吧!</p>
<a id="ps_aux"></a>
<ul><li>观察系统所有进程: ps aux</li></ul>
<table class="term"><tbody><tr><td class="term"><pre><span class="term_hd">范例二:列出目前所有的正在内存当中的进程:</span>
[root@study ~]# <span class="term_command">ps aux</span>
<span style="text-decoration: underline">USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND</span>
root 1 0.0 0.2 60636 7948 ? Ss Aug04 0:01 /usr/lib/systemd/systemd ...
root 2 0.0 0.0 0 0 ? S Aug04 0:00 [kthreadd]
<span class="term_say">.....(中间省略).....</span>
root 14830 0.0 0.1 210744 3988 pts/0 S Aug04 0:00 sudo su -
root 14835 0.0 0.1 202044 2996 pts/0 S Aug04 0:00 su -
<span style="text-decoration: underline">root 14836 0.0 0.1 116140 2960 pts/0 S Aug04 0:00 -bash</span>
<span class="term_say">.....(中间省略).....</span>
root 18459 0.0 0.0 123372 1380 pts/0 R+ 00:25 0:00 ps aux
</pre></td></tr></tbody></table>
<p>你会发现 ps -l 与 ps aux 显示的项目并不相同!在 ps aux 显示的项目中,各字段的意义为:</p>
<ul style="margin-left: 30px; list-style-type: square; color: #000000; font-family: '细明体'; ">
<li style="color: #252525;">USER:该 process 属于那个用户帐号的?</li>
<li style="color: #252525;">PID :该 process 的进程识别码。</li>
<li style="color: #252525;">%CPU:该 process 使用掉的 CPU 资源百分比;</li>
<li style="color: #252525;">%MEM:该 process 所占用的物理内存百分比;</li>
<li style="color: #252525;">VSZ :该 process 使用掉的虚拟内存量 (Kbytes)</li>
<li style="color: #252525;">RSS :该 process 占用的固定的内存量 (Kbytes)</li>
<li style="color: #252525;">TTY :该 process 是在那个终端机上面运作,若与终端机无关则显示 ?,另外, tty1-tty6
是本机上面的登录者进程,若为 pts/0 等等的,则表示为由网络连接进主机的进程。</li>
<li style="color: #252525;">STAT:该进程目前的状态,状态显示与 ps -l 的 S 旗标相同 (R/S/T/Z)</li>
<li style="color: #252525;">START:该 process 被触发启动的时间;</li>
<li style="color: #252525;">TIME :该 process 实际使用 CPU 运作的时间。</li>
<li style="color: #252525;">COMMAND:该进程的实际指令为何?</li>
</ul>
<p>一般来说,ps aux 会依照 PID 的顺序来排序显示,我们还是以 14836 那个 PID 那行来说明!该行的意义为『
root 运行的 bash PID 为 14836,占用了 0.1% 的内存容量百分比,状态为休眠 (S),该进程启动的时间为 8 月 4 号,因此启动太久了,
所以没有列出实际的时间点。且取得的终端机环境为 pts/0 。』与 ps aux 看到的其实是同一个进程啦!这样可以理解吗?
让我们继续使用 ps 来观察一下其他的信息吧!</p>
<table class="term"><tbody><tr><td class="term"><pre><span class="term_hd">范例三:以范例一的显示内容,显示出所有的进程:</span>
[root@study ~]# <span class="term_command">ps -lA</span>
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 1 0 0 80 0 - 15159 ep_pol ? 00:00:01 systemd
1 S 0 2 0 0 80 0 - 0 kthrea ? 00:00:00 kthreadd
1 S 0 3 2 0 80 0 - 0 smpboo ? 00:00:00 ksoftirqd/0
<span class="term_say">....(以下省略)....
# 你会发现每个字段与 ps -l 的输出情况相同,但显示的进程则包括系统所有的进程。</span>
<span class="term_hd">范例四:列出类似进程树的进程显示:</span>
[root@study ~]# <span class="term_command">ps axjf</span>
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 2 0 0 ? -1 S 0 0:00 [kthreadd]
2 3 0 0 ? -1 S 0 0:00 \_ [ksoftirqd/0]
<span class="term_say">.....(中间省略).....</span>
1 1326 1326 1326 ? -1 Ss 0 0:00 /usr/sbin/sshd -D
1326 13923 13923 13923 ? -1 Ss 0 0:00 \_ sshd: dmtsai [priv]
13923 13927 13923 13923 ? -1 S 1000 0:00 \_ sshd: dmtsai@pts/0
13927 13928 13928 13928 pts/0 18703 Ss 1000 0:00 \_ -bash
13928 13970 13970 13928 pts/0 18703 S 1000 0:00 \_ bash
13970 14830 14830 13928 pts/0 18703 S 0 0:00 \_ sudo su -
14830 14835 14830 13928 pts/0 18703 S 0 0:00 \_ su -
14835 14836 14836 13928 pts/0 18703 S 0 0:00 \_ -bash
14836 18703 18703 13928 pts/0 18703 R+ 0 0:00 \_ ps axjf
<span class="term_say">.....(后面省略).....</span>
</pre></td></tr></tbody></table>
<p>看出来了吧?其实鸟哥在进行一些测试时,都是以网络连接进虚拟机来测试的,所以啰,你会发现其实进程之间是有相关性的啦!
不过,其实还可以使用 pstree 来达成这个进程树喔!以上面的例子来看,鸟哥是透过 sshd 提供的网络服务取得一个进程,
该进程提供 bash 给我使用,而我透过 bash 再去运行 ps axjf !这样可以看的懂了吗?其他各字段的意义请 man ps
(虽然真的很难 man 的出来!) 啰!</p>
<table class="term"><tbody><tr><td class="term"><pre><span class="term_hd">范例五:找出与 cron 与 rsyslog 这两个服务有关的 PID 号码?</span>
[root@study ~]# <span class="term_command">ps aux | egrep '(cron|rsyslog)'</span>
root 742 0.0 0.1 208012 4088 ? Ssl Aug04 0:00 /usr/sbin/rsyslogd -n
root 1338 0.0 0.0 126304 1704 ? Ss Aug04 0:00 /usr/sbin/crond -n
root 18740 0.0 0.0 112644 980 pts/0 S+ 00:49 0:00 grep -E --color=auto (cron|rsyslog)
<span class="term_say"># 所以号码是 742 及 1338 这两个啰!就是这样找的啦!</span>
</pre></td></tr></tbody></table>
<a id="zombie"></a>
<p>除此之外,我们必须要知道的是『僵尸 (zombie) 』进程是什么?
通常,造成僵尸进程的成因是因为该进程应该已经运行完毕,或者是因故应该要终止了,
但是该进程的父进程却无法完整的将该进程结束掉,而造成那个进程一直存在内存当中。
如果你发现在某个进程的 CMD 后面还接上 <defunct> 时,就代表该进程是僵尸进程啦,例如:</p>
<table class="term"><tbody><tr><td class="term"><pre>apache 8683 0.0 0.9 83384 9992 ? Z 14:33 0:00 /usr/sbin/httpd <defunct>
</pre></td></tr></tbody></table>
<p>当系统不稳定的时候就容易造成所谓的僵尸进程,可能是因为程序写的不好啦,或者是用户的操作习惯不良等等所造成。
如果你发现系统中很多僵尸进程时,记得啊!要找出该进程的父进程,然后好好的做个追踪,好好的进行主机的环境最佳化啊!
看看有什么地方需要改善的,不要只是直接将他 kill 掉而已呢!不然的话,万一他一直产生,那可就麻烦了! @_@</p>
<p>事实上,通常僵尸进程都已经无法控管,而直接是交给 systemd 这支程序来负责了,偏偏 systemd 是系统第一支运行的程序,
他是所有程序的父程序!我们无法杀掉该程序的 (杀掉他,系统就死掉了!),所以啰,如果产生僵尸进程,
而系统过一阵子还没有办法透过核心非经常性的特殊处理来将该进程删除时,那你只好透过 reboot
的方式来将该进程抹去了!</p>
</div>
<a id="topm"></a>
<ul class="toplist"><li>top:动态观察进程的变化</li></ul>
<p>相对于 ps 是截取一个时间点的进程状态, top 则可以持续侦测进程运作的状态!使用方式如下:</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">top [-d 数字] | top [-bnp]</span>
<span class="term_say">选项与参数:
-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 软件的按键。</span>
</pre></td></tr></tbody></table>
<p>其实 top 的功能非常多!可以用的按键也非常的多!可以参考 man top 的内部说明文档!
鸟哥这里仅是列出一些鸟哥自己常用的选项而已。接下来让我们实际观察一下如何使用 top 与 top 的画面吧!</p>
<table class="term"><tbody><tr><td class="term"><pre><span class="term_hd">范例一:每两秒钟更新一次 top ,观察整体信息:</span>
[root@study ~]# <span class="term_command">top -d 2</span>
top - 00:53:59 up 6:07, 3 users, <span style="text-decoration: underline">load average: 0.00, 0.01, 0.05</span>
Tasks: 179 total, 2 running, 177 sleeping, 0 stopped, <span style="text-decoration: underline">0 zombie</span>
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, <span style="text-decoration: underline">0.0 wa</span>, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 2916388 total, 1839140 free, 353712 used, 723536 buff/cache
KiB Swap: 1048572 total, 1048572 free, <span style="text-decoration: underline"> 0 used</span>. 2318680 avail Mem
<span class="term_note"><==如果加入 k 或 r 时,就会有相关的字样出现在这里喔!</span>
<span style="background-color:white; color:black"> PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND </span>
18804 root 20 0 130028 1872 1276 R 0.5 0.1 0:00.02 top
1 root 20 0 60636 7948 2656 S 0.0 0.3 0:01.70 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.00 ksoftirqd/0
</pre></td></tr></tbody></table>
<p>top 也是个挺不错的进程观察工具!但不同于 ps 是静态的结果输出, top 这个程序可以持续的监测整个系统的进程工作状态。
在缺省的情况下,每次更新进程资源的时间为 5 秒,不过,可以使用 -d 来进行修改。
top 主要分为两个画面,上面的画面为整个系统的资源使用状态,基本上总共有六行,显示的内容依序是:</p>
<ul>
<li>第一行(top...):这一行显示的信息分别为:
<ul>
<li>目前的时间,亦即是 00:53:59 那个项目;</li>
<li>开机到目前为止所经过的时间,亦即是 up 6:07, 那个项目;</li>
<li>已经登录系统的用户人数,亦即是 3 users, 项目;</li>
<li>系统在 1, 5, 15 分钟的平均工作负载。我们在<a href="0430cron.html#batch">第十五章谈到的 batch</a>
工作方式为负载小于 0.8 就是这个负载啰!代表的是 1, 5, 15 分钟,系统平均要负责运作几个进程(工作)的意思。
越小代表系统越闲置,若高于 1 得要注意你的系统进程是否太过繁复了!</li>
</ul><br></li>
<li>第二行(Tasks...):显示的是目前进程的总量与个别进程在什么状态(running, sleeping, stopped, zombie)。
比较需要注意的是最后的 zombie 那个数值,如果不是 0 !好好看看到底是那个 process 变成僵尸了吧?<br><br></li>
<li>第三行(%Cpus...):显示的是 CPU 的整体负载,每个项目可使用 ? 查阅。需要特别注意的是 wa 项目,那个项目代表的是 I/O wait,
通常你的系统会变慢都是 I/O 产生的问题比较大!因此这里得要注意这个项目耗用 CPU 的资源喔!
另外,如果是多核心的设备,可以按下数字键『1』来切换成不同 CPU 的负载率。<br><br></li>
<li>第四行与第五行:表示目前的物理内存与虚拟内存 (Mem/Swap) 的使用情况。
再次重申,要注意的是 swap 的使用量要尽量的少!如果 swap 被用的很大量,表示系统的物理内存实在不足!<br><br></li>
<li>第六行:这个是当在 top 程序当中输入指令时,显示状态的地方。</li>
</ul>
<p>至于 top 下半部分的画面,则是每个 process 使用的资源情况。比较需要注意的是:</p>
<ul style="font-family: '细明体'">
<li>PID :每个 process 的 ID 啦!</li>
<li>USER:该 process 所属的用户;</li>
<li>PR :Priority 的简写,进程的优先运行顺序,越小越早被运行;</li>
<li>NI :Nice 的简写,与 Priority 有关,也是越小越早被运行;</li>
<li>%CPU:CPU 的使用率;</li>
<li>%MEM:内存的使用率;</li>
<li>TIME+:CPU 使用时间的累加;</li>
</ul>
<p>top 缺省使用 CPU 使用率 (%CPU) 作为排序的重点,如果你想要使用内存使用率排序,则可以按下『M』,
若要回复则按下『P』即可。如果想要离开 top 则按下『 q 』吧!如果你想要将 top 的结果输出成为文件时,
可以这样做:</p>
<table class="term"><tbody><tr><td class="term"><pre><span class="term_hd">范例二:将 top 的信息进行 2 次,然后将结果输出到 /tmp/top.txt</span>
[root@study ~]# <span class="term_command">top -b -n 2 > /tmp/top.txt</span>
<span class="term_say"># 这样一来,嘿嘿!就可以将 top 的信息存到 /tmp/top.txt 文件中了。</span>
</pre></td></tr></tbody></table>
<p>这玩意儿很有趣!可以帮助你将某个时段 top 观察到的结果存成文件,可以用在你想要在系统背景底下运行。
由于是背景底下运行,与终端机的屏幕大小无关,因此可以得到全部的进程画面!那如果你想要观察的进程 CPU
与内存使用率都很低,结果老是无法在第一行显示时,该怎办?我们可以仅观察单一进程喔!如下所示:</p>
<table class="term"><tbody><tr><td class="term"><pre><span class="term_hd">范例三:我们自己的 bash PID 可由 $$ 变量取得,请使用 top 持续观察该 PID</span>
[root@study ~]# <span class="term_command">echo $$</span>
14836 <span class="term_note"><==就是这个数字!他是我们 bash 的 PID</span>
[root@study ~]# <span class="term_command">top -d 2 -p 14836</span>
top - 01:00:53 up 6:14, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.1 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 2916388 total, 1839264 free, 353424 used, 723700 buff/cache
KiB Swap: 1048572 total, 1048572 free, 0 used. 2318848 avail Mem
<span style="background-color:white; color:black"> PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND</span>
<span style="text-decoration: underline">14836</span> root 20 0 116272 3136 1848 S 0.0 0.1 0:00.07 bash
</pre></td></tr></tbody></table>
<p>看到没!就只会有一支进程给你看!很容易观察吧!好,那么如果我想要在 top 底下进行一些动作呢?
比方说,修改 NI 这个数值呢?可以这样做:</p>
<table class="term"><tbody><tr><td class="term"><pre><span class="term_hd">范例四:承上题,上面的 NI 值是 0 ,想要改成 10 的话?</span>
<span class="term_say"># 在范例三的 top 画面当中直接按下 r 之后,会出现如下的图样!</span>
top - 01:02:01 up 6:15, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.1 us, 0.0 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 2916388 total, 1839140 free, 353576 used, 723672 buff/cache
KiB Swap: 1048572 total, 1048572 free, 0 used. 2318724 avail Mem
PID to renice [default pid = 14836] <span class="term_command">14836</span>
<span style="background-color:white; color:black"> PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND</span>
14836 root 20 0 116272 3136 1848 S 0.0 0.1 0:00.07 bash
</pre></td></tr></tbody></table>
<p>在你完成上面的动作后,在状态栏会出现如下的信息:</p>
<table class="term"><tbody><tr><td class="term"><pre>Renice PID 14836 to value <span class="term_command">10</span> <span class="term_note"><==这是 nice 值</span>
<span style="background-color:white; color:black"> PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND</span>
</pre></td></tr></tbody></table>
<p>接下来你就会看到如下的显示画面!</p>
<table class="term"><tbody><tr><td class="term"><pre>top - 01:04:13 up 6:17, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 2916388 total, 1838676 free, 354020 used, 723692 buff/cache
KiB Swap: 1048572 total, 1048572 free, 0 used. 2318256 avail Mem
<span style="background-color:white; color:black"> PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND</span>
14836 root <span style="text-decoration: underline">30 10</span> 116272 3136 1848 S 0.0 0.1 0:00.07 bash
</pre></td></tr></tbody></table>
<p>看到不同处了吧?底线的地方就是修改了之后所产生的效果!一般来说,如果鸟哥想要找出最损耗 CPU
资源的那个进程时,大多使用的就是 top 这支程序啦!然后强制以 CPU 使用资源来排序 (在 top 当中按下 P 即可),
就可以很快的知道啦! ^_^。多多爱用这个好用的东西喔!</p>
<a id="pstree"></a>
<ul class="toplist"><li>pstree</li></ul>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">pstree [-A|U] [-up]</span>
<span class="term_say">选项与参数:
-A :各进程树之间的连接以 ASCII 字符来连接;
-U :各进程树之间的连接以万国码的字符来连接。在某些终端接口下可能会有错误;
-p :并同时列出每个 process 的 PID;
-u :并同时列出每个 process 的所属帐号名称。</span>
<span class="term_hd">范例一:列出目前系统上面所有的进程树的相关性:</span>
[root@study ~]# <span class="term_command">pstree -A</span>
systemd-+-ModemManager---2*[{ModemManager}] <span class="term_note"># 这行是 ModenManager 与其子进程</span>
|-NetworkManager---3*[{NetworkManager}] <span class="term_note"># 前面有数字,代表子进程的数量!</span>
<span class="term_say">....(中间省略)....</span>
|-sshd---sshd---sshd---bash---bash---sudo---su---bash---pstree <span class="term_note"><==我们指令运行的相依性</span>
<span class="term_say">....(底下省略)....</span>
<span class="term_say"># 注意一下,为了节省版面,所以鸟哥已经删去很多进程了!</span>
<span class="term_hd">范例二:承上题,同时秀出 PID 与 users </span>
[root@study ~]# <span class="term_command">pstree -Aup</span>
systemd(1)-+-ModemManager(745)-+-{ModemManager}(785)
| `-{ModemManager}(790)
|-NetworkManager(870)-+-{NetworkManager}(907)
| |-{NetworkManager}(911)
| `-{NetworkManager}(914)
<span class="term_say">....(中间省略)....</span>
|-sshd(1326)---sshd(13923)---sshd(13927,<span class="term_write">dmtsai</span>)---bash(13928)---bash(13970)---
<span class="term_say">....(底下省略)....</span>
<span class="term_say"># 在括号 () 内的即是 PID 以及该进程的 owner 喔!一般来说,如果该进程的所有人与父进程同,
# 就不会列出,但是如果与父进程不一样,那就会列出该进程的拥有者!看上面 13927 就转变成 dmtsai 了</span>
</pre></td></tr></tbody></table>
<p>如果要找进程之间的相关性,这个 pstree 真是好用到不行!直接输入 pstree
可以查到进程相关性,如上表所示,还会使用线段将相关性进程链接起来哩!
一般链接符号可以使用 ASCII 码即可,但有时因为语系问题会主动的以 Unicode 的符号来链接,
但因为可能终端机无法支持该编码,或许会造成乱码问题。因此可以加上 -A 选项来克服此类线段乱码问题。</p>
<p>由 pstree 的输出我们也可以很清楚的知道,<span class="text_import2">所有的进程都是依附在 systemd 这支进程底下的!
仔细看一下,这支进程的 PID 是一号喔!因为他是由 Linux 核心所主动调用的第一支程序!所以 PID 就是一号了</span>。
这也是我们刚刚提到<a href="0440processcontrol.html#zombie">僵尸进程</a>时有提到,为啥发生僵尸进程需要重新开机?
因为 systemd 要重新启动,而重新启动 systemd 就是 reboot 啰!</p>
<p>如果还想要知道 PID 与所属用户,加上 -u 及 -p 两个参数即可。我们前面不是一直提到,
如果子进程挂点或者是老是砍不掉子进程时,该如何找到父进程吗?呵呵!用这个 pstree 就对了! ^_^</p>
<br></div><br>
<a id="process_2"></a>
<div class="block2"><div class="gototop"><a href="0440processcontrol.html#top">Top</a></div>
<h2>16.3.2 进程的管理</h2>
<p>进程之间是可以互相控制的!举例来说,你可以关闭、重新启动服务器软件,服务器软件本身是个进程,
你既然可以让她关闭或启动,当然就是可以控制该进程啦!<span class="text_import2">那么进程是如何互相管理的呢?其实是透过给予该进程一个信号 (signal)
去告知该进程你想要让她作什么!</span>因此这个信号就很重要啦!</p>
<a id="signal"></a>
<p>我们也在本章之前的 <a href="0440processcontrol.html#background">bash 工作管理</a>当中提到过,
要给予某个已经存在背景中的工作某些动作时,是直接给予一个信号给该工作号码即可。那么到底有多少 signal 呢?
你可以使用 kill -l (小写的 L ) 或者是 man 7 signal 都可以查找到!主要的信号代号与名称对应及内容是:</p>
<table class="news" style="width: 95%">
<tbody><tr class="theader"><td style="width: 40px">代号</td><td style="width: 50px">名称</td><td>内容</td></tr>
<tr><td class="tcenter">1</td><td class="tcenter">SIGHUP</td><td>启动被终止的进程,可让该 PID 重新读取自己的设置档,类似重新启动</td></tr>
<tr><td class="tcenter">2</td><td class="tcenter">SIGINT</td><td>相当于用键盘输入 [ctrl]-c 来中断一个进程的进行</td></tr>
<tr><td class="tcenter">9</td><td class="tcenter">SIGKILL</td><td>代表强制中断一个进程的进行,如果该进程进行到一半,
那么尚未完成的部分可能会有『半产品』产生,类似 vim会有 .filename.swp 保留下来。</td></tr>
<tr><td class="tcenter">15</td><td class="tcenter">SIGTERM</td><td>以正常的结束进程来终止该进程。由于是正常的终止,
所以后续的动作会将他完成。不过,如果该进程已经发生问题,就是无法使用正常的方法终止时,
输入这个 signal 也是没有用的。</td></tr>
<tr><td class="tcenter"><a id="20130802"></a>19</td><td class="tcenter">SIGSTOP</td><td>相当于用键盘输入 [ctrl]-z 来暂停一个进程的进行</td></tr>
</tbody></table>
<p>上面仅是常见的 signal 而已,更多的信号信息请自行 man 7 signal 吧!一般来说,你只要记得『1, 9,
15』这三个号码的意义即可。那么我们如何发送一个信号给某个进程呢?就透过 kill 或 killall 吧!底下分别来看看:</p>
<a id="kill"></a>
<ul class="toplist"><li>kill -signal PID</li></ul>
<p>kill 可以帮我们将这个 signal 发送给某个工作 (%jobnumber) 或者是某个 PID (直接输入数字)。
要再次强调的是: <span class="text_import2">kill 后面直接加数字与加上 %number 的情况是不同的</span>!
这个很重要喔!因为工作控制中有 1 号工作,但是 PID 1 号则是专指『 systemd 』这支程序!你怎么可以将 systemd 关闭呢?
关闭 systemd ,你的系统就当掉了啊!所以记得那个 % 是专门用在工作控制的喔!
我们就活用一下 kill 与刚刚上面提到的 ps 来做个简单的练习吧!</p>
<table class="exam" style="width: 95%"><tbody><tr><td>
例题:<div>
以 ps 找出 rsyslogd 这个进程的 PID 后,再使用 kill 发送消息,使得 rsyslogd 可以重新读取设置档。
</div>
答:<div>
由于需要重新读取设置档,因此 signal 是 1 号。至于找出 rsyslogd 的 PID 可以是这样做:
<blockquote style="font-family: '细明体'; font-size:10pt; color: #000088">ps aux | grep 'rsyslogd' | grep -v 'grep'| awk '{print $2}'</blockquote>
接下来则是实际使用 kill -1 PID,因此,整串指令会是这样:
<blockquote style="font-family: '细明体'; font-size:9pt; color: #000088">kill -SIGHUP $(ps aux | grep 'rsyslogd' | grep -v 'grep'| awk '{print $2}')</blockquote>
如果要确认有没有重新启动 syslog ,可以参考注册表的内容,使用如下指令查阅:
<blockquote style="font-family: '细明体'; font-size:10pt; color: #000088">tail -5 /var/log/messages</blockquote>
如果你有看到类似『Aug 5 01:25:02 study rsyslogd: [origin software="rsyslogd" swVersion="7.4.7" x-pid="742" x-info="http://www.rsyslog.com"] rsyslogd
was HUPed』之类的字样,就是表示 rsyslogd 在 8/5 有重新启动 (restart) 过了!
</div>
</td></tr></tbody></table>
<p>了解了这个用法以后,如果未来你想要将某个莫名其妙的登录者的连接删除的话,就可以透过使用 pstree -p 找到相关进程,
然后再以 kill -9 将该进程删除,该条连接就会被踢掉了!这样很简单吧!</p>
<a id="killall"></a>
<ul class="toplist"><li>killall -signal 指令名称</li></ul>
<p>由于 kill 后面必须要加上 PID (或者是 job number),所以,通常 kill 都会配合
<a href="0440processcontrol.html#ps">ps</a>, <a href="0440processcontrol.html#pstree">pstree</a> 等指令,因为我们必须要找到相对应的那个进程的
ID 嘛!但是,如此一来,很麻烦~有没有可以利用『下达指令的名称』来给予信号的?举例来说,能不能直接将 rsyslogd
这个进程给予一个 SIGHUP 的信号呢?可以的!用 killall 吧!</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">killall [-iIe] [command name]</span>
<span class="term_say">选项与参数:
-i :interactive 的意思,交互式的,若需要删除时,会出现提示字符给用户;
-e :exact 的意思,表示『后面接的 command name 要一致』,但整个完整的指令
不能超过 15 个字符。
-I :指令名称(可能含参数)忽略大小写。</span>
<span class="term_hd">范例一:给予 rsyslogd 这个指令启动的 PID 一个 SIGHUP 的信号</span>
[root@study ~]# <span class="term_command">killall -1 rsyslogd</span>
<span class="term_say"># 如果用 ps aux 仔细看一下,若包含所有参数,则 /usr/sbin/rsyslogd -n 才是最完整的!</span>
<span class="term_hd">范例二:强制终止所有以 httpd 启动的进程 (其实并没有此进程在系统内)</span>
[root@study ~]# <span class="term_command">killall -9 httpd</span>
<span class="term_hd">范例三:依次询问每个 bash 程序是否需要被终止运作!</span>
[root@study ~]# <span class="term_command">killall -i -9 bash</span>
Signal bash(13888) ? (y/N) <span class="term_command">n</span> <span class="term_note"><==这个不杀!</span>
Signal bash(13928) ? (y/N) <span class="term_command">n</span> <span class="term_note"><==这个不杀!</span>
Signal bash(13970) ? (y/N) <span class="term_command">n</span> <span class="term_note"><==这个不杀!</span>
Signal bash(14836) ? (y/N) <span class="term_command">y</span> <span class="term_note"><==这个杀掉!</span>
<span class="term_say"># 具有交互的功能!可以询问你是否要删除 bash 这个程序。要注意,若没有 -i 的参数,
# 所有的 bash 都会被这个 root 给杀掉!包括 root 自己的 bash 喔! ^_^</span>
</pre></td></tr></tbody></table>
<p>总之,要删除某个进程,我们可以使用 PID 或者是启动该进程的指令名称,
而如果要删除某个服务呢?呵呵!最简单的方法就是利用 killall ,
因为他可以将系统当中所有以某个指令名称启动的进程全部删除。
举例来说,上面的范例二当中,系统内所有以 httpd 启动的进程,就会通通的被删除啦! ^_^</p>
<br></div><br>
<a id="priority"></a>
<div class="block2"><div class="gototop"><a href="0440processcontrol.html#top">Top</a></div>
<h2>16.3.3 关于进程的运行顺序</h2>
<p>我们知道 Linux 是多人多任务的环境,由 <a href="0440processcontrol.html#topm">top</a> 的输出结果我们也发现,
系统同时间有非常多的进程在运行中,只是绝大部分的进程都在休眠 (sleeping) 状态而已。
想一想,如果所有的进程同时被唤醒,那么 CPU 应该要先处理那个进程呢?也就是说,那个进程被运行的优先序比较高?
这就得要考虑到进程的优先运行序 (Priority) 与 CPU 调度啰!</p>
<fieldset class="vbirdface"><legend style="font-family: serif; font-size:12pt; color: darkblue;">Tips</legend><img src="./vbird_files/vbird_face.gif" alt="鸟哥的图标" title="鸟哥的图标" style="float: right;"> CPU 调度与前一章的例行性工作调度并不一样。 CPU 调度指的是每支进程被 CPU 运作的演算规则,
而例行性工作调度则是将某支程序安排在某个时间再交由系统运行。 CPU 调度与操作系统较具有相关性!
</fieldset><br>
<a id="pri"></a>
<ul class="toplist"><li>Priority 与 Nice 值</li></ul>
<p>我们知道 CPU 一秒钟可以运作多达数 G 的微指令次数,透过核心的 CPU 调度可以让各进程被 CPU 所切换运作,
因此每个进程在一秒钟内或多或少都会被 CPU 运行部分的脚本。如果进程都是集中在一个队列中等待 CPU 的运作,
而不具有优先级之分,也就是像我们去游乐场玩热门游戏需要排队一样,每个人都是照顺序来!
你玩过一遍后还想再玩 (没有运行完毕),请到后面继续排队等待。情况有点像底下这样:</p>
<a id="fig16.3.1"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/pri_cpu_no.gif" alt="并没有优先级的进程队列示意图" title="并没有优先级的进程队列示意图" style="border: 1px solid black; padding: 10px "></div>
<div style="text-align: center;">图16.3.1、并没有优先级的进程队列示意图</div>
<p>上图中假设 pro1, pro2 是紧急的进程, pro3, pro4 是一般的进程,在这样的环境中,由于不具有优先级,
唉啊!pro1, pro2 还是得要继续等待而没有优待呢!如果 pro3, pro4 的工作又臭又长!那么紧急的 pro1, pro2
就得要等待个老半天才能够完成!真麻烦啊!所以啰,我们想要将进程分优先级啦!如果优先序较高则运作次数可以较多次,
而不需要与较慢优先的进程抢位置!我们可以将进程的优先级与 CPU 调度进行如下图的解释:</p>
<a id="fig16.3.2"></a>
<div style="text-align:center; margin: 0 auto 0 auto; "><img src="./vbird_files/pri_cpu_yes.gif" alt="具有优先级的进程队列示意图" title="具有优先级的进程队列示意图" style="border: 1px solid black; padding: 10px "></div>
<div style="text-align: center;">图16.3.2、具有优先级的进程队列示意图</div>
<p>如上图所示,具高优先权的 pro1, pro2 可以被取用两次,而较不重要的 pro3, pro4 则运作次数较少。
如此一来 pro1, pro2 就可以较快被完成啦!要注意,上图仅是示意图,并非较优先者一定会被运作两次啦!
为了要达到上述的功能,我们 Linux 给予进程一个所谓的『优先运行序 (priority, PRI)』,
这个 <span class="text_import2">PRI 值越低代表越优先的意思。不过这个 PRI 值是由核心动态调整的,
用户无法直接调整 PRI 值的。</span>先来瞧瞧 PRI 曾在哪里出现?</p>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">ps -l</span>
F S UID PID PPID C <span class="term_write">PRI NI</span> ADDR SZ WCHAN TTY TIME CMD
4 S 0 14836 14835 0 <span class="term_write">90 10</span> - 29068 wait pts/0 00:00:00 bash
0 R 0 19848 14836 0 <span class="term_write">90 10</span> - 30319 - pts/0 00:00:00 ps
<span class="term_say"># 你应该要好奇,怎么我的 NI 已经是 10 了?还记得刚刚 top 的测试吗?我们在那边就有改过一次喔!</span>
</pre></td></tr></tbody></table>
<p>由于 PRI 是核心动态调整的,我们用户也无权去干涉 PRI !那如果你想要调整进程的优先运行序时,就得要透过 Nice
值了!Nice 值就是上表的 NI 啦!一般来说, PRI 与 NI 的相关性如下:</p>
<blockquote class="text_import2">PRI(new) = PRI(old) + nice</blockquote>
<p>不过你要特别留意到,如果原本的 PRI 是 50 ,并不是我们给予一个 nice = 5 ,就会让 PRI 变成 55 喔!
因为 PRI 是系统『动态』决定的,所以,虽然 nice 值是可以影响 PRI ,不过,
最终的 PRI 仍是要经过系统分析后才会决定的。另外, nice 值是有正负的喔,而既然 PRI 越小越早被运行,
所以,<span class="text_import2">当 nice 值为负值时,那么该进程就会降低 PRI
值,亦即会变的较优先被处理。</span>此外,你必须要留意到:</p>
<ul>
<li>nice 值可调整的范围为 -20 ~ 19 ;</li>
<li>root 可随意调整自己或他人进程的 Nice 值,且范围为 -20 ~ 19 ;</li>
<li>一般用户仅可调整自己进程的 Nice 值,且范围仅为 0 ~ 19 (避免一般用户抢占系统资源);</li>
<li>一般用户仅可将 nice 值越调越高,例如本来 nice 为 5 ,则未来仅能调整到大于 5;</li>
</ul>
<p>这也就是说,要调整某个进程的优先运行序,就是『调整该进程的 nice 值』啦!那么如何给予某个进程 nice
值呢?有两种方式,分别是:</p>
<ul class="text_import2">
<li>一开始运行程序就立即给予一个特定的 nice 值:用 nice 指令;</li>
<li>调整某个已经存在的 PID 的 nice 值:用 renice 指令。</li></ul>
<a id="nice"></a>
<ul class="toplist"><li>nice :新运行的指令即给予新的 nice 值</li></ul>
<table class="term"><tbody><tr><td class="term"><pre>[root@study ~]# <span class="term_command">nice [-n 数字] command</span>
<span class="term_say">选项与参数:
-n :后面接一个数值,数值的范围 -20 ~ 19。</span>
<span class="term_hd">范例一:用 root 给一个 nice 值为 -5 ,用于运行 vim ,并观察该进程!</span>
[root@study ~]# <span class="term_command">nice -n -5 vim &</span>
[1] 19865
[root@study ~]# <span class="term_command">ps -l</span>
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 14836 14835 0 90 10 - 29068 wait pts/0 00:00:00 bash
4 T 0 19865 14836 0 <span class="term_write">85 5</span> - 37757 signal pts/0 00:00:00 vim
0 R 0 19866 14836 0 90 10 - 30319 - pts/0 00:00:00 ps
<span class="term_say"># 原本的 bash PRI 为 90 ,所以 vim 缺省应为 90。不过由于给予 nice 为 -5 ,
# 因此 vim 的 PRI 降低了!RPI 与 NI 各减 5 !但不一定每次都是正好相同喔!因为核心会动态调整</span>
[root@study ~]# <span class="term_command">kill -9 %1</span> <span class="term_note"><==测试完毕将 vim 关闭</span>
</pre></td></tr></tbody></table>
<p>就如同前面说的, nice 是用来调整进程的运行优先级!这里只是一个运行的范例罢了!
通常什么时候要将 nice 值调大呢?举例来说,系统的背景工作中,
某些比较不重要的进程之进行:例如备份工作!由于备份工作相当的耗系统资源,
这个时候就可以将备份的指令之 nice 值调大一些,可以使系统的资源分配的更为公平!</p>
<a id="renice"></a>