第6章Linux进程 6.1 及第24章 Shell编程 LINUX启动 选择shell ? /etc/shells文件中列出了系统可以运行的shell的列 表 ?/bin目录下有shell的执行程序 ? /etc/passwd文件列出了每个用户的登录shell 改变shell ? #chsh –s /bin/ash ? #chsh –s /bin/bash ? #chsh –s /bin/csh Bash的配置文件 ?在用户登录时,Bash初始化的配置文件: – /home/wangke/.bash_profile ?在每次进入Bash或生成subshell时执行的配置文 件: – / home/wangke/.bashrc – /home/wangke/ .bash_login ?在退出Bash时执行的配置文件: – / home/wangke/.bashrc Shell程序设计 ?Shell的两层含义: –指由Shell命令组成的Shell命令语言 –指该命令语言的解释程序 ?流行的Shell: – Bourne shell(UNIX System V使用,提示符$,程序 名是sh) –C shell(BSD UNIX使用,提示符%,程序名是csh) –Korn shell(结合了上面两者的优点) – Bash(GNU Linux缺省Shell) Shell程序设计 ?Shell程序设计语言 –可以定义变量、关键字 –有各种控制结构: ?顺序结构 ?分支结构if case ?循环结构while for until –有语法结构 –可灵活地利用位置参数传递参数值 ? UNIX/Linux程序员常常利用Shell语言,把 UNIX/Linux命令组合在一起,编写出功能很强但 代码简单的程序。 Shell程序的编写与运行 ?一个最简单的Shell程序例子: $cat file1 # count files in current directory ls -l | wc –l $ 说明:用任何纯文本编辑器均可,建议文件名加.sh表明这是一个Shell程序文件。 ?程序运行方法(4种) 第一种:$bash file1 第二种:$bash < file1 第三种:$chmod a+x file1 $./file1 第四种:$. file1 Shell程序设计 ?Shell程序设计语言的变量 –环境变量 –位置参数变量 –用户自定义变量 环境变量 ?与系统的工作环境有关的专用变量: man 指令的搜寻路径 $MANPATH 每隔多少秒检查是否有新的信件 $MAILCHECK 时区 $TZ 执行上一个指令的返回值 $? 执行上一个背景指令的PID $! 命令行参数个数 $# Shell的所有参数 $* Shell的PID $$ 辅助提示符,在命令结束前遇到换行时,在续行中使用的提示符,系统默认为“>”.如 $echo “first <CR> > second” $PS2 主提示符,表示shell等待输入命令。在特权用户下,主提示符默认为“#” $PS1 终端类型 $TERM 存放用户邮件的邮箱文件名 $MAIL 执行命令时所搜寻的目录 $PATH 用户注册后的当前目录,cd命令的缺省参数,每个用户具有不同值 $HOME 查看环境变量 ? #printenv 临时设置环境变量 ? #env PATH=&PATH:/usr/wangk 位置参数变量 ?Shel程序的命令参数由分割符分开,被从左到右依次赋 给位置参数$0, $1, $2……第一个命令参数为$1,第二个 命令参数为$2,……依次类推。$0表示命令名(shell程 序名)。 ?示例程序 $cat postfile echo The first: $1 echo The second: $2 echo The third: $3 echo The fourth: $4 echo The program name: $0 $ ?执行过程及结果 $sh postfile first second third fourth The first: first The second: second The third: third The fourth: fourth The program name: postfile $ Shell程序的shift命令 ?Shel程序的位置参数只能使用$1——$9,但Shell程序的 命令行中允许使用128个命令参数。这时就必须使用 shift命令来存取$9以上的参数。 ?示例程序 $cat file.shift echo Before shift, the parameters: $0,$1,$2,$3,$4,$5,$6,$7,$8,$9 echo No of parameters: $# shift echo After shift,the parameters: $0,$1,$2,$3,$4,$5,$6,$7,$8,$9 echo No of parameters: $# $ Shell程序的shift语句 ?执行过程及结果 $file.shift 1 2 3 4 5 6 7 8 9 Before shift, the parameters: file.shift,1,2,3,4,5,6,7,8,9 No of parameters: 9 After shift,the parameters: file.shift,2,3,4,5,6,7,8,9 echo No of parameters: 8 $ ?shift命令重新命名所有的位置参数变量:$2成为 $1,$3成为$2等。每使用一次shift,都使所有的 位置参数依次向左移动一个位置,并使位置参数 的数量减1,直至减为0。$0不受Shift命令的影响。 用户自定义变量 ?用户自定义变量语法: 定义方法:变量名=string –变量名由字母或下划线打头,由字母、下划线、数字组成。 –=表示赋值运算符,两边不能有空格 引用方法:$变量名 ?示例程序 $cat file TIME=“Data and time: \c” USERS=“No of users: \c” HOST=“Personal stat: \c” echo $TIME date echo $USERS who | wc –l echo $HOST whoami $ ?执行过程及结果 $file Data and time: mon Dec 16:00:00 CST 2003 No of users: 3 Personal stat: Wang Ke tty 01 Dec 15 08:00 wangk $ Shell程序结构程序结构 如何指定使用哪一个Shell 来解释所写的Script呢?几种 基本的指定方式如下所述: 1. 如果Script的第一个非空白字符不是"#",则它会使用 Bourne Shell。 2. 如果Script的第一个非空白字符是"#"时,但不以"#!"开 头时,则它会使用C Shell。 3. 如果Script以“#!”开头,则“#!”後面所写的就是所使用 的Shell,而且要将整个路径名称指出来。例如: #! /bin/bash Shell程序结构程序结构 Script是以行为单位,Script会分解成一行一行来执行。 而每一行可以是命令、注解、或是流程控制指令等。如 果某一行尚未完成,可以在行末加上“\”,这个时候下一 行的内容就会接到这一行的後面,成为同一行。 当Script中出现“#”时,再它後面的同一行文字即为注解, Shell 不会对其翻译。 Shell程序结构 ?分支结构?循环结构 if 命令1 … … 命令m then 命令1 … … 命令n else 命令1 … … 命令n fi for 变量名 [in 数值列表] do 命令1 命令2 … 命令n done while 命令1 … 命令m do 命令1 命令2 … 命令n done ?if语句示例程序 $cat seekword echo type a word and file name read WORD FILE //读入参数值,相当于scanf if grep $WORD $FILE //从文件$FILE 中查找字符串$WORD then echo the $WORD is a word of the $FILE fi $ ?if语句示例程序 $cat username # check the passwd file for login NAME = ${1 – root} //给出缺省的位置参数:$1的值缺省为root NULLNAME = /dev/null //用户自定义变量:/dev/null是系统的空文件 if grep $NAME /etc/passwd > $NULLNAME then echo $NAME is a passwd file elif grep $NAME /etc/group > $NULLNAME then echo $NAME is a group file. else echo the $NAME is not a passwd file name either or a group file. fi $ ?执行过程及结果 $username root is a passwd file $username wangk wangk is a passwd file $ ?While循环示例程序 $cat md # put a list of name into file echo “type in each person’s name the a <CR>” echo “type the list of name with <Ctrl-D>” while read name do echo $name >> namefile done echo namefile contains the follow names: cat namefile $ 说明:因为< >是输入输出重定向符号,要把它们变成普通字符, echo 语句必须加“” ?for循环示例程序 $cat movefile.file # move file to another directory. echo type a path read DESTIPATH for VARFILE in file1 file2 file3 do mv $VARFILE $DESTIPATH/$VARFILE done $ For语句的工作过程: ?如果命令中含有in 列表,则用in之后的数值顺序替换循环体列表中的“$ 变量名”; ?如果for语句中省略了in列表,则用位置参数来替换循环体列表中的“$ 变量名”; ?对每一个数值都执行do…done之间的命令列表。 6.2 Linux进程 ? 6.2.1 进程 ? 6.2.2 多进程 ? 6.2.3 运行后台进程(& nohup cron crontab anacron at atq atrm batch) ? 6.2.4 启动多个进程(at batch) ? 6.2.5 进程的控制(ps) ? 6.2.6 用户退出后继续运行的进程(nohup) ? 6.2.7 调整进程优先级(& nice renice) ? 6.2.8 终止进程(kill) 6.2.3 运行后台进程 ?概念:前台后台 ?运行后台进程的方法 –命令行末尾添加“&”符号 – nohup命令 –cron命令 – crontab命令 –anacron命令 –at命令(atq atrm命令) – batch命令 Linux进程的状态 32 16 8 4 2 1 0 值 僵死态,表示进程结束但尚未消亡的一种状态。此时,进程已 经结束运行且释放大部分资源,但尚未释放PCB TASK _ZOMBIE 不可中断等待态。处于等待队列中的进程,待资源有效时唤醒, 不可由其它进程通过信号(Signal)或定时中断唤醒后进入就绪队 列 TASK _UNINTERRUPTABLE 说明进程状态 运行态。实际包含了执行态和就绪态两种状态 TASK_RUNNING 可中断等待态。处于等待队列中的进程,待资源有效时唤醒, 也可由其它进程通过信号(Signal)或定时中断唤醒后进入就绪队 列 TASK _INTERRUPTABLE 独占态。处于独占态的进程位于等待队列中。如果有一组进程 都在等待某一事件,一旦事件发生,只有处于独占态的进程被 唤醒,其它处于可中断态和不可中断态的进程则继续等待。 TASK_EXCLUSIVE 交换态。页面被交换出内存的进程。2.4.X版本中已无此状态。 TASK_SWAPPING 暂停态,进程需要通过其它进程的信号才能唤醒。导致这种状 态的原因有二:或者是对收到SIGSTOP、SIGSTP、SIGTTIN、 SIGTTOU信号的反应;或者是受其它进程的ptrace系统调用而 暂时将CPU交给跟踪它的进程。比如处于调试跟踪的进程,每 执行到一个断点,就转入暂停态,等待新的输入信号。 TASK _STOPPED Linux进程的标志(Flag) 进程被信号杀出 PF_SIGNALED 进程正被创建 PF_STARTING 进程开始关闭 PF_EXITING 该进程使用FPU(用于SMP) PF_USEDFPU Delayed trace(用于M68K) PF_DTRACE 进程刚创建,但还没执行 PF_FORKNOEXEC 正在跟踪 PF_TRACESYS 说明进程标志 打印“对齐”警告信息 PF_ALIGNWARN 被ptrace系统调用跟踪 PF_PTRACED Dumped core PF_DUMPCORE 超级用户特权 PF_SUPERPRIV Linux进程的状态转换 Lin ux 的 软 中 断 信 号 ps命令 Ordered by real user ID -U Only running process -r Ordered by process ID -p full -f All except session leaders -d All processes -A All w/ tty except session leaders -a Ordered by command name -C All processes on this terminal -T Job control -j Ordered by real group ID -G ? #ps --help ps命令 进程睡眠,或处于SXBRK 状态的事件的地址(如果为空,则进程正在运行) WCHAN 进程的控制终端 TTY 进程的累计执行时间 TIME 虚拟内存的大小 SZ 进程的内存地址 ADDR 命令名(在–f 选项下显示命令名及其参数) CMD 父进程的PID PPID 进程的ID PID 与进程有关的标志 F 进程的状态 S 进程所有者的用户ID(在–f 选项下显示注册名) UID Nice值,用于优先级的计算 NI 进程的优先级 PRI CPU的利用率 C 调整进程优先级 ?在启动进程时指定优先级nice ?在进程运行时调整优先级renice nice命令 ?(优先)数值越大,优先权越低。 ?除了root,其它用户只能自我降低优先权。 显示帮助信息 --help 在原有(优先)数值上+n -n 显示版本号 --version renice命令 ? renice priority [[-p]pids] [[-g]pgrps] [[-u]users] ?除了root,其它用户只能自我降低优先权。 标志后面是进程组号,即按进程组好来改变进程的优先级 -g 标志后面是进程号,即按进程号来改变进程的优先级 -p 标志后面是用户名,即按用户名来改变进程的优先级 -u kill命令 ? kill [-s signal | -p] [-a] pid ? Kill –l [signal] -l PID -p -s -9 nohup命令 ?运行命令不受挂起和退出的影响。如果用户未用输出改 向,则标准输出和标准错误输出都被送到nohup.out。如 果当前目录中的nohup.out不可写,则输出改向到 $HOME/nohup.out ?可以将多个命令放入shell文件中,以实现后台运行多个命 令 #nohup sh file1 ? P.125 #nohup dir > lsecho & -l PID -p -s -9 配置cron ?cron可以定时地、周期地执行程序 ? crond是cron的守护进程 ?cron的主配置文件是/etc/crontab 文件 ?cron的执行任务必须以crontab格式在一个文本文件中描述,该文 件通常由crontab命令生成 ?用户定义的crontab被保存在/var/spool/cron/$USER文件中 ? crond每分钟都去检查/etc/crontab文件、/etc/cron.d目录、 /var/spool/cron目录中的任何改变 ?控制文件(/etc/cron.allow和/etc/cron.deny)被用来限制用户对cron 的使用。如果/etc/cron.allow文件存在,仅允许这个文件里列出的 用户使用cron。如果/etc/cron.deny这个文件存在,该文件列出的 用户都不能使用cron服务。当这个文件为空时,任何用户都可以 使用cron,这是默认配置。 ?当运行cron时,先检查/etc/cron.allow文件是否存在,如果不存在, 再检查/etc/cron.deny文件是否存在。 crontab命令 ? #crontab [-u user] file ? #crontab [-u user] file {-e | -l | -r} Delete user’s crontab -r 用指定的文件替代当前的crontab file Edit usr’s crontab -e Minute Hour Day Month Dayofweek Command 文件格式 List user’s crontab -l ? #gedit crontest 0 8 * * * date>crontest ? #crontab crontest at命令 ?可以在shell提示符下输入at time ?可以在shell提示符下输入at –f script ?控制文件(/etc/at.allow和/etc/at.deny)被用来限制用户对at的使用。 如果/etc/at.allow文件存在,仅允许这个文件里列出的用户使用at。 如果/etc/at.deny这个文件存在,该文件列出的用户都不能使用at 服务。当这个文件为空时,任何用户都可以使用at,这是默认配 置。 ?当运行at命令时,先检查/etc/at.allow文件是否存在,如果不存在, 再检查/etc/at.deny文件是否存在。不管这两个文件是不是存在, root用户都可以执行at命令 at命令 ? #at [-V] [-q x] [-f script] [-m] time [-l] 打印版本号 -V 指定可选队列的名称。队列可以是a-z或A-Z之间的任意字母。C队列是at的 默认值,而E队列是batch的默认值。队列的字母位置越高,运行CPU时间的 优先权越低。 -q 从队列中取消指定编号的作业 -r 作业完成后,即使没有输出,也将邮件送到用户 -m 从名为script的文件中读取要执行的作业任务,而不是从标准输入读取-f script 作业开始的时间。格式包括3个部分:时间、日期、增值。At可接受的时间 形式是HHMM或HH:MM,在时间后可加AM或PM,并在一天中指定的时间 运行作业;如果时间过去了,就在第二天执行。日期的格式为MMDDYY或 MM/DD/YY或DD.MM.YY。还可以这样给出时间:now+若干时间单位(可 以是分钟、小时、天、星期;还可以加today、tomorrow。 time 列出现在安排的作业,若是超级用户则列出所有作业 -l