shell 多进程基础
代码块: 用 { } 囊括, 作为一个整体
& 作用: 将命令放于后台处理, 空闲出当前控制台以用于做其他操作
wait 命令: 等待父进程的子进程都执行结束后再执行父进程中的指令
trap 命令: 获取控制信号, 并作出处理; 格式: trap CAMMANDS SIGNAL
通过 exec 执行: 创建一个新的同 PID 的进程去处理, 变量共用, 执行完 exec 内容后, 不回到原来的调用
通过 fork 执行: 创建新进程 (子进程) 处理, 变量只能单向传递
通过 source 执行: 加载到同一进程, 在同一控制台串行处理, 变量共用, 执行完 source 内容后, 再回到原来的地方接着处理
多进程关键点
文件描述符:
是一个索引值, 是内核为每一个进程与进程所打开的文件的一个映射记录表. 当程序打开一个现有文件或者创建一个新文件时, 内核向进程返回一个文件描述符.
文件与描述符关系: 每一个文件描述符会对应一个打开文件; 不同的文件描述符可以对应同一个打开文件; 同一个文件可以被不同的进程打开, 也可以被同一个进程多次打开.
默认描述符:/proc/self/fd (0,1,2)
自定义描述符:
可用范围: ulimit -n 查看, 再除去默认的 0,1,2
管道: 类似于队列
特点:
对管道的读写操作应同时进行, 不然操作就会被滞留
按行为单位进行操作
匿名管道: 常用的 "|", 前一个命令的标准输出作为下一个命令的标准输入
有名管道: 一般作为任务队列, 有序存取
使用 mkfifo 命令创建一个有名管道
3. 管道与文件描述符关联
- mkfifo /tmp/$$.fifo
- exec 5 <>/tmp/$$.fifo
- rm -f /tmp/$$.fifo
文件描述符与管道绑定: 解决管道读写必须同时存在的特性
删除管道: 系统调用 exec 是以新的进程去代替原来的进程, 但进程的 PID 保持不变
多进程实例
mysql 分库备份
- #!/bin/bash
- hour=`date +%H`
- day=`date +%F`
- now=`date +%F_%H`
- all_dbs="no"
- passwd="mysql_pass"
- sshpass="ssh_pass"
- dbs="db1 db2 db3 dbx dby dbz"
- cpu_num=`cat /proc/cpuinfo |grep processor|wc -l`
- p_fifo="/tmp/$$.pipo"
- mkfifo $p_fifo
- exec 111<>$p_fifo #关联文件描述符和管道
- rm -f $p_fifo
- trap "exec 111>&-;exec 111<&-;exit 0" 2
- for ((i=1; i<=$cpu_num; i++))
- do
- echo>&111 #定义进程队列大小, cpu 核数
- done
- function backup()
- {
- if [ $all_dbs == "no" ];then
- for db in $dbs
- do
- read -u111 #从队列中获取一个消息, 队列中消息数减一
- {
- dbname=`echo $db|sed "s/-/@002d/g"`
- ops="--parallel=5 --compress-threads=5 --databases=$dbname"
- bpath="/data1/ehr-mysql-backup/${day}/${db}"
- inbackup
- sleep 10
- echo>&111 #添加一个消息到队列中, 维持队列中消息数不变 (进程个数)
- } & #将代码块放后台处理
- done
- wait #等待所有后台进程处理完
- exec 111>&- #关闭描述符, 读写分开关闭
- exec 111<&-
- else
- ops="--parallel=5 --compress-threads=5"
- bpath="/data1/ehr-mysql-backup/${day}"
- inbackup
- fi
- }
- function inbackup()
- {
- if [ -f ${bpath}/lsn_${last}/xtrabackup_checkpoints ];then
- echo "incremental_basedir found,do a increment backup"
- /usr/bin/innobackupex -u root -p${passwd} --no-timestamp ${ops} --incremental --incremental_basedir=${bpath}/lsn_${last}/ --extra-lsndir=${bpath}/lsn_${now}/ ${bpath} --stream=xbstream |gzip |sshpass -p "${sshpass}" ssh -p 18122 root@10.10.10.79 "cat -> ${bpath}/${now}.xbstram.gz"
- else
- echo "incremental_basedir not found,do a full backup"
- /usr/bin/innobackupex -u root -p${passwd} --no-timestamp ${ops} --extra-lsndir=${bpath}/lsn_${now}/ ${bpath} --stream=tar |gzip |sshpass -p "${sshpass}" ssh -p 18122 root@10.10.10.79 "cat -> ${bpath}/${now}.tgz"
- fi
- }
- case $hour in
- 22)
- last=`date +%F -d -yesterday`
- find /data1/ehr-mysql-backup/ -name "${last}*" -type d -exec rm -r "{}" \;
- day=`date +%F -d +1days`
- backup
- ;;
- 10)
- last=`date +%F_%H -d -12hours`
- backup
- ;;
- 14|18)
- last=`date +%F_%H -d -4hours`
- backup
- ;;
- *)
- echo "not backup time"
- ;;
- esac
来源: http://www.bubuko.com/infodetail-2637578.html