当前位置: 首页 > Linux

zsh开发指南(Part15ProcessandJobControl)

时间:2023-04-06 20:45:36 Linux

简介通常zsh脚本都是在一个进程中执行的(而且是单线程的),但是有时候我们需要并行执行一些代码,因为现在的CPU基本都是多核的,可以加快运算速度。这涉及过程和作业控制。这里不讨论进程的概念。在子进程中执行代码我们之前提到,括号中的代码是在子进程中执行的:%(sleep1000&&echogood)#然后在另一个zsh中查看进程%pstree|grepsleep`-tmux:server-+-zsh---zsh---有两个zsh进程处于睡眠状态。如果不加括号:%sleep1000&&echogood#然后在另一个zsh中查看进程%pstree|grepsleep`-tmux:server-+-zsh---sleep只有一个zsh进程。这意味着当使用括号时,里面的代码是在子进程(一个新的zsh进程)中执行的。但需要注意的是,如果括号内只有一个命令(比如sleep1000),那么就不会开启另一个子进程执行。那么在子进程中执行代码有什么意义呢?如果你像上面那样在前台运行它没有多大意义。但是我们可以让它在后台运行。在后台运行进程首先,让我们看看如何让单个程序在后台运行。%sleep1000&[1]850在sleep1000后加一个&,它会在后台运行。然后会输出一行内容,[1]是进程的作业号,850是进程号(PID)。我们可以继续运行其他命令,而无需等待睡眠结束。jobs命令可以查看当前后台运行的所有作业:%jobs[1]+runningsleep1000#-l会输出进程号%jobs-l[1]+850runningsleep1000fg该命令可以将后台作业切换回theforeground:#然后会继续等待sleep运行%fg[??1]+runningsleep1000如果进程已经在运行了,我们又想把它放到后台,那么可以这样做:#Pressctrl+z%sleep1000^Zzsh:suspendedafterenteringsleep1000#这时候可以运行jobs看到,sleep处于暂停状态%jobs[1]+suspendedsleep1000#可以用bg恢复sleep%bg[1]+continuedsleep1000#这样sleep运行在后台是%jobs[1]+runningsleep1000其实jobs,fg,bg这些命令并不常用,了解一下用法即可.比如我正在用vim编辑一个文件,但是文件还没有保存,但是我想回到终端运行一个命令,然后再回到vim。可以按ctrl+z暂停vim,然后运行命令,最后运行fg恢复vim。但通常我们可以启动多个终端仿真器,或者打开一个新的终端仿真器选项卡,或者使用tmux,不需要再折腾一个shell。使用后台进程执行脚本中的代码然后回答前面的场景,在后台进程中执行sleep1000&&echogood:%{sleep1000&&echoaa}&这样大括号中的代码就会在后台执行过程,在脚本中可以继续写其他的。如果你完成了,你需要等待大括号里面的代码运行。#!/bin/zsh{sleep5&&echop1}&#$!是最后运行的后台进程的进程号pid=$!{sleep10&&echop2}&echoaaa#先做其他事情finishsleep2echobbb#wait添加进程号等待进程结束,类似fg,但是脚本中不能使用fgwait$pidechocccresult:%./test.zshaaabbbp1ccc#p2是脚本运行几秒后的%p2输出,所以我们可以同时操作多个进程来服务你自己。进程之间的通信可以用命名管道或者普通文件,或者socket文件(Zsh中有zsh/net/socket模块,可以通过socket文件进行通信。管道是单向的,而socket是双向的,更灵活,后面我们会了解它的用法),或者使用网络通信(如果脚本分布在不同的机器上,zsh中有一个zsh/net/tcp模块,这样就可以在没有外部命令的情况下进行tcp通信,后续也会讨论)。信号一个正在运行的进程可以接收信号然后响应它们。kill命令用于向进程发送信号。15(SIGTERM)是最常用的信号,也是kill不带参数的默认信号,用来终止一个进程。killnum可以终止进程号为num的进程。但是15信号可以被进程捕获然后不退出。如果想强行杀掉一个进程,可以使用9信号(SIGKILL),这个信号是无法被进程捕获的,但是这样的话,进程正在做的事情会突然中断,可能会造成严重的影响,所以通常不要使用9信号来终止进程。捕获脚本中的信号:#!/bin/zsh#SIGINT是2个信号,ctrl+c会触发TRAPINT(){#handlesomepost-exitworksleep333}sleep1000然后运行这个脚本,然后ctrl+c,脚本并没有退出,因为执行了sleep333,只有再次按下才会退出。在脚本中使用信号时,通常会将它们发送给其他进程(主要是15个),而不是发送给自己。也几乎不需要在脚本中捕获信号处理。将来可能会添加更多与信号相关的内容。总结本文大致讲了进程和作业控制相关的内容,主要用于在脚本中使用多进程代码执行,而不是在终端中进行作业控制(因为很少用到)。关于脚本中的多个进程如何协同工作还有很多工作要做。本文不再更新,全系列文章更新维护在这里:github.com/goreliu/zshguideWindows、Linux、Shell、C、C++、AHK、Python、JavaScript、Lua等相关问题的付费解决方案,定价灵活,欢迎咨询,微信ly50247。