13 子Shell与进程处理
2015-03-13 14:47
225 查看
13.1 子Shell
Shell本身也是一个程序,也可以启动自己的子进程,这些子进程称为子Shell。作为初学者,必须搞清楚子Shell与其父Shell的区别与联系以及Shell命令与子Shell的关系。本节将对子Shell的基础知识进行介绍。
13.1.1 什么是子Shell
所谓子Shell,实际上是父Shell的一个子进程。子Shell本身也可以创建自己的子进程,从而成为其子进程的父Shell。从定义可以看出,父Shell和子Shell都是相对的。某个Shell可以成为一个Shell的父Shell,也可以同时成为另外一个Shell的子Shell,反之亦然。在环境变量以及标准输入、标准输出和标准错误等方面,父Shell和子Shell是相同的。
#! /bin/bash
cd /var/log
pwd
13.1.2 内部命令、保留字和外部命令
Shell命令分为内部命令和外部命令。所谓内部命令,是指包含在Shell工具包中的命令,内部命令是Shell本身的重要组成部分。内部命令嵌入在Shell程序中,并不单独以磁盘文件的形式存在于磁盘上。例如cd、bg以及fg等命令都是bash Shell的内部命令。
bash常用的内部命令
. 读取shell脚本,并在当前脚本中执行
alias 设置命令别名
bg 将作业置于后台运行
cd 改变当前工作目录
echo 打印指定的文本
eval 将参数作为shell命令执行
exec 以特定的程序取代shel或者改变当前shell的输出输入
exit 退出shell
export 将变量声明为环境变量
fc 与命令历史一起运行
fg 将作业置于前台运行
getopts 处理命令行选项
history 显示命令历史
jobs 显示在后台运行的作业
kill 向进程发信号
logout 从shell中注销
pwd 显示当前工作目录
set 设置(显示)shell环境变量
shift 变换命令行参数
#! /bin/bash
ps -ef|grep ps
echo $SHLVL
pidof -x ex13-2.sh
exit 0
13.1.3 在子Shell中执行命令
1.圆括号结构
当一组命令放在圆括号中时,该组命令会在一个子Shell环境中执行,其语法如下:
(command1;command2;command3;...)
在上面的语法中,command1、command2以及command3等都是Shell命令,这些命令些在一行中,它们之间用分号隔开。
#!/bin/bash
echo
echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL"
echo
outer_variable=Outer
(
echo "Subshell level INSIDE subshell = $BASH_SUBSHELL"
inner_variable=Inner
echo "From subshell, \"inner_variable\" = $inner_variable"
echo "From subshell, \"outer\" = $outer_variable"
)
echo
echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL"
echo
if [ -z "$inner_variable" ] ;then
echo "inner_variable undefined in main body of shell"
else
echo "inner_variable defined in main body of shell"
fi
echo "From main body of shell, \"inner_variable\" = $inner_variable"
echo
exit 0
#!/bin/bash
echo "Before starting subshell"
(
count=1
while [ $count -le 10 ]
do
echo "$count"
sleep 1
(( count++ ))
done
) &
echo "Finished"
2.后台执行或异步执行
在某些情况下,Shell命令需要较长的时间来执行,尤其是在处理大量的数据的时候。在这种情况下,用户可以将命令置于后台执行,而不必等待命令执行结束。
将命令置于后台执行的语法如下:
command &
#! /bin/bash
echo "generating a background child process"
for ((i=9; i>=0; i--))
do
sleep 1
echo -e "\rsleeping ${i}s ...\c"
done &
## 创建后台进程
## 获取最近创建的后台进程的PID
BG_PID=$!
echo "child process's PID is ${BG_PID}"
3.命令替换
命令替换的语法如下:
`command`
或者
$(command)
其中,command表示要执行的命令。command会在一个子Shell中执行,不会影响到当前的Shell环境。
#! /bin/bash
(cd /;ls;echo "current working directory is ";pwd)
echo "current working directory is"
pwd
13.1.4 把子Shell中的变量值传回父Shell
在子Shell中,代码可以访问父Shell的变量;反之,在父Shell中,却无法访问到子Shell中的变量的值。但是,用户可以通过一些变通的技巧来取得子Shell中的变量的值。下面分别进行介绍。
1.通过临时文件
在Linux中,通过临时文件传递数据是一个非常重要的技巧,许多地方都使用到。对于磁盘文件来说,只要拥有足够的权限,任何进程都可以访问到。另外,通过临时文件,用户可以在进程之间传递大量的数据,不会受到内存空间的限制。
#! /bin/bash
(
x=500
echo "$x" >tmp
)
echo "$x"
read b <tmp
echo "$b"
2.使用命名管道
命名管道是Linux以及UNIX系统中的最古老的进程间通信的方式,同时也是一个相对比较简单的通信机制。
#! /bin/bash
if [ ! -e fifo ];then
mkfifo fifo
fi
(
x=500
echo "$x" > fifo
)&
read y <fifo
echo "$y"
3.不使用子Shell
之所以出现以上变量传递问题,是因为使用了子Shell。如果不使用子Shell,则以上问题就不存在。当用户在某个Shell脚本中调用另外一个脚本时,被调用的脚本会在子Shell中执行。但是,用户可以通过圆点命令和source命令来执行脚本,使得被调用的脚本在当前Shell进程中执行。
#! /bin/bash
echo "$message"
#! /bin/bash
message="Hello world."
source ./output.sh
13.2 进程处理
在进行系统维护的过程中,经常会遇到进程和作业的处理问题。通过Shell编程,用户可以对进程和作业进行有效地管理。本节介绍如何通过Shell进行进程的相关操作。
13.2.1 什么是进程
进程是指在自身的虚拟地址空间运行的一个单独的程序,是程序执行的基本单元。进程会利用处理器资源、内存资源,并且进行各种I/O操作,从而完成某项指定的任务。因此,进程是一个动态的概念。
13.2.2 通过脚本监控进程
通常情况下,通过脚本来监控进程可以收到事半功倍的效果。例如,在绝大部分的Web服务器都是运行在Linux上面。但是在某些情况下,Web服务器的进程httpd会由于某些错误而退出,导致用户的网站不能访问。而系统管理员则不可能会24小时都在监控Web服务器的运行状态。
#! /bin/bash
RESTART="/sbin/service httpd restart"
PGREP="/usr/bin/pgrep"
HTTPD="httpd"
$PGREP ${HTTPD} &>/dev/null
if [ $? -ne 0 ] ;then
$RESTART
fi
13.2.3 作业控制
作业控制指的是用户控制正在运行的组成作业的进程的行为。在前面已经介绍过,用户可以在命令的后面附加&操作符,使得该命令在后台执行。另外,用户还可以将作业中的某个进程挂起,暂停其执行,然后在某个时刻再继续执行该进程。
#! /bin/bash
sleep 10
13.2.4 信号与trap命令
信号在Linux系统中非常重要的一种通信机制。信号在软件层次上模拟了硬件中断机制。因此,简单地讲,信号即软件中断。在Linux系统中,用户可以通过kill命令给某个进程发送一个特定的信号,也可以通过键盘发送一些信号,比如组合键CTRL+C可能触发 SIGINT信号,而组合键CTRL+\可能触发SIGQUIT信号等。
kill [-s signal|-p] [--] pid...
trap [[arg] sigspec ...]
#! /bin/bash
function signal_handler {
echo "Good bye."
}
trap signal_handler 0
Shell本身也是一个程序,也可以启动自己的子进程,这些子进程称为子Shell。作为初学者,必须搞清楚子Shell与其父Shell的区别与联系以及Shell命令与子Shell的关系。本节将对子Shell的基础知识进行介绍。
13.1.1 什么是子Shell
所谓子Shell,实际上是父Shell的一个子进程。子Shell本身也可以创建自己的子进程,从而成为其子进程的父Shell。从定义可以看出,父Shell和子Shell都是相对的。某个Shell可以成为一个Shell的父Shell,也可以同时成为另外一个Shell的子Shell,反之亦然。在环境变量以及标准输入、标准输出和标准错误等方面,父Shell和子Shell是相同的。
#! /bin/bash
cd /var/log
pwd
13.1.2 内部命令、保留字和外部命令
Shell命令分为内部命令和外部命令。所谓内部命令,是指包含在Shell工具包中的命令,内部命令是Shell本身的重要组成部分。内部命令嵌入在Shell程序中,并不单独以磁盘文件的形式存在于磁盘上。例如cd、bg以及fg等命令都是bash Shell的内部命令。
bash常用的内部命令
. 读取shell脚本,并在当前脚本中执行
alias 设置命令别名
bg 将作业置于后台运行
cd 改变当前工作目录
echo 打印指定的文本
eval 将参数作为shell命令执行
exec 以特定的程序取代shel或者改变当前shell的输出输入
exit 退出shell
export 将变量声明为环境变量
fc 与命令历史一起运行
fg 将作业置于前台运行
getopts 处理命令行选项
history 显示命令历史
jobs 显示在后台运行的作业
kill 向进程发信号
logout 从shell中注销
pwd 显示当前工作目录
set 设置(显示)shell环境变量
shift 变换命令行参数
#! /bin/bash
ps -ef|grep ps
echo $SHLVL
pidof -x ex13-2.sh
exit 0
13.1.3 在子Shell中执行命令
1.圆括号结构
当一组命令放在圆括号中时,该组命令会在一个子Shell环境中执行,其语法如下:
(command1;command2;command3;...)
在上面的语法中,command1、command2以及command3等都是Shell命令,这些命令些在一行中,它们之间用分号隔开。
#!/bin/bash
echo
echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL"
echo
outer_variable=Outer
(
echo "Subshell level INSIDE subshell = $BASH_SUBSHELL"
inner_variable=Inner
echo "From subshell, \"inner_variable\" = $inner_variable"
echo "From subshell, \"outer\" = $outer_variable"
)
echo
echo "Subshell level OUTSIDE subshell = $BASH_SUBSHELL"
echo
if [ -z "$inner_variable" ] ;then
echo "inner_variable undefined in main body of shell"
else
echo "inner_variable defined in main body of shell"
fi
echo "From main body of shell, \"inner_variable\" = $inner_variable"
echo
exit 0
#!/bin/bash
echo "Before starting subshell"
(
count=1
while [ $count -le 10 ]
do
echo "$count"
sleep 1
(( count++ ))
done
) &
echo "Finished"
2.后台执行或异步执行
在某些情况下,Shell命令需要较长的时间来执行,尤其是在处理大量的数据的时候。在这种情况下,用户可以将命令置于后台执行,而不必等待命令执行结束。
将命令置于后台执行的语法如下:
command &
#! /bin/bash
echo "generating a background child process"
for ((i=9; i>=0; i--))
do
sleep 1
echo -e "\rsleeping ${i}s ...\c"
done &
## 创建后台进程
## 获取最近创建的后台进程的PID
BG_PID=$!
echo "child process's PID is ${BG_PID}"
3.命令替换
命令替换的语法如下:
`command`
或者
$(command)
其中,command表示要执行的命令。command会在一个子Shell中执行,不会影响到当前的Shell环境。
#! /bin/bash
(cd /;ls;echo "current working directory is ";pwd)
echo "current working directory is"
pwd
13.1.4 把子Shell中的变量值传回父Shell
在子Shell中,代码可以访问父Shell的变量;反之,在父Shell中,却无法访问到子Shell中的变量的值。但是,用户可以通过一些变通的技巧来取得子Shell中的变量的值。下面分别进行介绍。
1.通过临时文件
在Linux中,通过临时文件传递数据是一个非常重要的技巧,许多地方都使用到。对于磁盘文件来说,只要拥有足够的权限,任何进程都可以访问到。另外,通过临时文件,用户可以在进程之间传递大量的数据,不会受到内存空间的限制。
#! /bin/bash
(
x=500
echo "$x" >tmp
)
echo "$x"
read b <tmp
echo "$b"
2.使用命名管道
命名管道是Linux以及UNIX系统中的最古老的进程间通信的方式,同时也是一个相对比较简单的通信机制。
#! /bin/bash
if [ ! -e fifo ];then
mkfifo fifo
fi
(
x=500
echo "$x" > fifo
)&
read y <fifo
echo "$y"
3.不使用子Shell
之所以出现以上变量传递问题,是因为使用了子Shell。如果不使用子Shell,则以上问题就不存在。当用户在某个Shell脚本中调用另外一个脚本时,被调用的脚本会在子Shell中执行。但是,用户可以通过圆点命令和source命令来执行脚本,使得被调用的脚本在当前Shell进程中执行。
#! /bin/bash
echo "$message"
#! /bin/bash
message="Hello world."
source ./output.sh
13.2 进程处理
在进行系统维护的过程中,经常会遇到进程和作业的处理问题。通过Shell编程,用户可以对进程和作业进行有效地管理。本节介绍如何通过Shell进行进程的相关操作。
13.2.1 什么是进程
进程是指在自身的虚拟地址空间运行的一个单独的程序,是程序执行的基本单元。进程会利用处理器资源、内存资源,并且进行各种I/O操作,从而完成某项指定的任务。因此,进程是一个动态的概念。
13.2.2 通过脚本监控进程
通常情况下,通过脚本来监控进程可以收到事半功倍的效果。例如,在绝大部分的Web服务器都是运行在Linux上面。但是在某些情况下,Web服务器的进程httpd会由于某些错误而退出,导致用户的网站不能访问。而系统管理员则不可能会24小时都在监控Web服务器的运行状态。
#! /bin/bash
RESTART="/sbin/service httpd restart"
PGREP="/usr/bin/pgrep"
HTTPD="httpd"
$PGREP ${HTTPD} &>/dev/null
if [ $? -ne 0 ] ;then
$RESTART
fi
13.2.3 作业控制
作业控制指的是用户控制正在运行的组成作业的进程的行为。在前面已经介绍过,用户可以在命令的后面附加&操作符,使得该命令在后台执行。另外,用户还可以将作业中的某个进程挂起,暂停其执行,然后在某个时刻再继续执行该进程。
#! /bin/bash
sleep 10
13.2.4 信号与trap命令
信号在Linux系统中非常重要的一种通信机制。信号在软件层次上模拟了硬件中断机制。因此,简单地讲,信号即软件中断。在Linux系统中,用户可以通过kill命令给某个进程发送一个特定的信号,也可以通过键盘发送一些信号,比如组合键CTRL+C可能触发 SIGINT信号,而组合键CTRL+\可能触发SIGQUIT信号等。
kill [-s signal|-p] [--] pid...
trap [[arg] sigspec ...]
#! /bin/bash
function signal_handler {
echo "Good bye."
}
trap signal_handler 0
相关文章推荐
- Linux shell编程 13 ---- 子Shell与进程处理
- Shell 编程12(子shell和进程处理)
- 关闭用户打开的进程处理
- 启动一个进程并处理进程结束事件
- 未处理的异常:进程性能计数器已禁用
- 启动一个进程并处理进程结束事件
- uclinux-2008r1-rc8(bf561)的中断处理(7):evt_evt7-13
- InnoDB中文参考手册---13出错处理
- 调用wait&waitpid来处理终止的子进程
- 巧妙设置Sybase用户权限来处理进程
- semget函数 semopt 采用信号量处理多进程互斥同步
- InnoDB 中文参考手册 --- 13 出错处理
- Unix定时进程处理
- Windows API 函数学习(13)---进程函数示例
- 在多个子进程处理SOCKET发信,程序很简单,有不好的地方请指点,运行环境AIX
- PHP5的异常处理机制[13]--获得异常相关的更多信息
- fork exec对子进程继承父进程信号处理机制的影响--APUE
- IIS 6进程CPU占用率50%,一段时间后,网站崩掉,如何处理? (downmoon)
- 利用勾子监视系统或进程中的各种事件消息,截获发往目标窗口的消息并进行处理