当前位置: 首页 > Linux

MIT计算机教育遗漏课笔记:命令行环境

时间:2023-04-06 01:59:03 Linux

_写在前面:本文内容来自MIT开设的课程:计算机教育遗漏课,介绍命令行,强大的文字使用编辑器,使用版本控制系统提供的各种功能,等等。中文课程主页。本文内容为第五节:命令行环境。本节的主要内容如下:如何同时执行多个不同的进程并跟踪它们的状态,如何停止或暂停一个进程,如何让一个进程在后台运行。一些改进shell等工具工作流程的方法,主要是定义别名或者根据配置文件进行配置如何使用SSH操作远程机器任务控制结束进程Shell会使用UNIX提供的信令机制进行进程间通信。当进程接收到信号时,它会停止执行,处理信号,并根据信号传递的信息改变其执行。因此,信号是一种_软件中断_。当我们键入Ctrl-C时,shell会向进程发送一个SIGINT(中断程序)信号。另一个退出程序的信号:SIGQUIT(退出程序),可以通过Ctrl-\触发。尽管SIGINT和SIGQUIT都经常用于发出与终止程序相关的请求。SIGTERM是一个更通用、更优雅的退出信号。要发送这个信号,我们需要使用kill命令,它的语法是:kill-TERM。挂起和后台进程在终端中,键入Ctrl-Z将导致shell发送SIGTSTP信号。此时程序暂停,并没有结束。使用jobs命令查看当前会话中的进程。当程序挂起时,可以使用fg命令继续执行挂起的程序,也可以使用bg命令将程序置于后台继续执行。您可以通过作业打印结果中的进程标签来参考某个进程。例如进程标签为[1],则可以使用bg%1在后台运行该进程,也可以通过kill%1将其杀死。过程。执行命令时,在末尾加上&,让程序直接在后台执行。但是注意这个进程仍然是终端的子进程,所以当终端关闭的时候,这个进程也会被终止(此时发出的信号是SIGHUP)。为了防止这种情况,可以在程序开头使用nohup程序:nohup命令command_options,然后关闭终端,程序会继续执行。以下代码演示了这些命令:?sleep1000^Z[1]+60227suspendedsleep1000?nohupsleep2000&[2]60237将输出附加到nohup.out?jobs[1]+suspendedsleep1000[2]-运行nohupsleep2000?bg%1[1]-60227继续睡眠1000?作业[1]-运行sleep1000[2]+运行nohupsleep2000?kill%1[1]-60227终止睡眠1000?作业[2]+运行nosleep2000?kill-SIGHUP%2?jobs[2]+runningnohupsleep2000?kill%2[2]+60237terminatednohupsleep2000?jobs以下是Linux系统中的信号列表,可以查询通过mansignal:NoNameDefaultActionDescription1SIGHUPterminateprocessterminallinehangup2SIGINTterminateprocessinterruptprogram3SIGQUITcreatecoreimagequitprogram4SIGILLcreatecoreimageillegalinstruction5SIGTRAPcreatecoreramimagetraceprogramt(formSIGABRTimageabcoreerlySIGIOT)7SIGEMT创建核心图像仿真指令已执行8SIGFPE创建核心图像浮点异常9SIGKILL终止进程终止程序10SIGBUS创建核心图像总线错误11SIGSEGV创建核心图像分段违规12SIGSYS创建核心图像不存在的系统调用已调用13SIGPIPE终止进程在没有读取器的管道上写入14SIGALRM终止进程实时计时器已过期15SIGTERM终止进程软件终止信号16SIGURG丢弃信号紧急情况出现在套接字上17SIGSTOP停止进程停止(无法捕获或忽略)18SIGTSTPstopprocessstopsignalgeneratedfromkeyboard19SIGCONTdiscardsignalcontinueafterstop20SIGCHLDdiscardsignal子状态已更改21SIGTTIN停止进程后台读取尝试从控制终端读取22SIGTTOU停止进程后台写入尝试控制终端23SIGIO丢弃信号I/O在描述符上是可能的(参见fcntl(2))24SIGXCPU终止进程cpu时间超出限制(请参阅setrlimit(2))25SIGXFSZ终止进程文件大小超出限制(请参阅setrlimit(2))26SIGVTALRM终止进程虚拟时间警报(请参阅setitimer(2))27SIGPROF终止进程分析计时器警报(请参阅setitimer(2)))28SIGWINCHdiscardsignal窗口大小改变29SIGINFOdiscardsignalstatusrequestfromkeyboard30SIGUSR1terminateprocessUserdefinedsignal131SIGUSR2terminateprocessUserdefinedsignal2终端多路复用(Terminalmultiplexer)来自维基百科的解释:终端多多路复用器是一种软件应用程序,可用于在单个终端显示器、终端仿真器窗口、PC/工作站系统控制台或telnet会话或从终端分离和重新连接会话中多路复用多个独立的基于伪终端的登录会话常用的终端复用软件是tmux。tmux中有3个非常重要的概念,分别是:session、window和panel。有很多重要的快捷键需要掌握:session——每个session都是一个独立的workspace,包含一个或多个窗口,在Terminal输入tmux来开始一个新的sessiontmuxnew-sNAME来开始一个指定名称的新sessiontmuxls来列出所有当前会话在tmux中输入d(detach)以分离当前会话tmuxa以重新连接上一个会话。也可以使用-tNAME来指定特定的会话窗口——相当于浏览器中的编辑器或标签页,可视化地将一个会话分成多个部分c(create)创建一个新窗口,使用来关闭它N跳转到第N个窗口,注意每个窗口都有编号p切换到上一个窗口n切换到下一个窗口,重命名当前窗口w列出所有当前窗口面板-就像vim中的分屏一样,面板允许我们在一个屏幕中显示多个外壳指键盘上的方向键z切换当前面板的缩放(将当前面板缩放到最大)[开始向后滚动屏幕。可以按空格键开始选区,回车复制选区(很有用)is:aliasalias_name="commandarg1arg2",这里有几个例子:#为常用命令创建缩写aliasll="ls-lh"#可以保存很多aliasgs="gitstatus"aliasgc="gitcommit"aliasv="vim"#不小心输入错误的命令也没关系aliassl=ls#重新定义一些命令行的默认行为aliasmv="mv-i"#-i在覆盖前提示aliasmkdir="mkdir-p"#-p根据需要制作父目录aliasdf="df-h"#-h打印人类可读格式#别名可以组合使用aliasla="ls-A"aliaslla="la-l"#ignoredAnalias\ls#ordisablealiasunaliasla#得到别名的定义aliasll#会打印ll='ls-lh'需要把你要设置别名的代码保存到shell的启动文件中,比如作为.bashrc或.zshrc。配置文件一些常用的配置文件位于用户目录下,以.开头:bash-~/.bashrc或~/.bash_profilegit-~/.gitconfigvim-~/.vimrc和~/.vim目录ssh-~/。ssh/configtmux-~/.tmux.conf推荐的管理这些配置文件的方式:将这些文件放在一个目录下,然后通过git控制版本,通过link将文件链接到对应的文件。这样做的好处是显而易见的:如果有多台电脑需要配置,可以一键配置;并且更改后的配置也会同步到每台电脑上。远程设备通过ssh连接远程服务器,服务器可以通过URL(如bar.mit.edu)或IP(如foobar@192.168.1.42)指定。通过sshfoobar@serverls可以直接在服务器上执行ls命令,在只执行一条命令的时候非常方便。使用私钥连接远程服务器时,需要向服务器证明客户端持有相应的私钥。在本地生成私钥:使用ssh-keygen。将公钥传给服务器有两种方式:#第一种方式,直接上传cat.ssh/id_ed25519.pub|sshfoobar@remote'cat>>~/.ssh/authorized_keys'#第二种方式,需要本地支持ssh-copy-idssh-copy-id-i.ssh/id_ed25519.pubfoobar@remote通过SSH拷贝文件,可以使用scp命令,语法为:scppath/to/local_fileremote_host:path/to/remote_file。更好的方法是使用rsync,它通过检测本地和远程文件来改进scp以防止重复副本。使用SSH端口转发的端口转发有两种:本地端口转发和远程端口转发。一个常见的场景是使用本地端口转发,即远程设备上的服务监听一个端口,你想在本地设备的某个端口上建立连接,转发到远程端口。例如,我们在侦听端口8888的远程服务器上运行JupyterNotebook。然后,要从本地端口9999建立转发,请使用ssh-L9999:localhost:8888foobar@remote_server。这样只需要访问本地localhost:9999即可。SSH配置文件由于各种选项的存在,SSH命令可能会很长。我们可以通过配置~/.ssh/config文件来保存服务器的配置。这个文件可以被scp、rsync等命令读取,并转换成相应的命令行选项。配置示例:HostvmUserfoobarHostName172.16.174.141Port2222IdentityFile~/.ssh/id_ed25519LocalForward9999localhost:8888#配置文件中也可以使用通配符Host*.mit.eduUserfoobaz命令如psaux|grep获取任务的pids,然后你可以根据pids杀死进程。但我们实际上有更好的方法来做到这一点。在终端中执行sleep10000任务。然后使用Ctrl-Z将其切换到后台并使用bg继续执行。现在,使用pgrep查找pid并使用pkill终止进程,而无需手动输入pid。(提示:使用-af标志)。?sleep10000^Z[1]+62750suspendedsleep10000?bg[1]+62750continuedsleep10000?pgrepsleep62750?pkill-afsleep[1]+62750terminatedsleep10000afterstartinganotherprocessifyouwant实现过程?在本练习中,我们使用sleep60&作为第一个要执行的程序。一种方法是使用等待命令。尝试启动hibernate命令,然后在它完成后执行ls命令。?sleep10&[3]62850#wait只能等待当前shell的子进程?wait62850;ls[3]+62850donesleep10但是,如果我们在不同的bash会话中操作,上面的方法就不行了。因为`wait`只能作用于子进程。我们之前没有提到的一项功能是,“kill”命令成功退出时状态代码为“0”,否则状态代码不是“0”。`kill-0`不会发送信号,但如果进程不存在,将返回`0`以外的状态码。请编写一个`bash`函数`pidwait`以`pid`作为输入并等待进程结束。您需要使用`sleep`以避免浪费`CPU`性能。`wait`程序实现:```bashmyWait(){pid=$1whiletrue;如果[[$?-eq0]];thenecho"processexists,waitfor1seconds..."sleep1elsebreakfidoneecho"进程完成!"ls}```将程序保存为`wait.sh`,程序执行和结果:```bash?sourcewait.sh?sleep10^Z[1]+63612suspendedsleep10?bg[1]+63612continuedsleep10?myWait63612进程存在,等待1秒...进程存在,等待1秒...进程存在,等待1秒...进程存在,等待1秒...进程存在,等待1秒秒...[1]+63612donesleep10myWait:kill:3:kill63612failed:nosuchprocessprocessfinished!wait.sh```terminalmultiplexingpleasethroughthistmuxtutorial:https://www.hamvocke.com/blog/a-quick-and-easy-guide-to-tmux/按照以下步骤学习如何自定义tmux:https://www.hamvocke.com/blog/a-guide-to-customizing-your-tmux-conf/配置文件是位于:~/.tmux.conf将前缀从Ctrl+b替换为Ctrl+a以便于输入#将前缀从'C-b'重新映射到'C-a'取消绑定C-bset-option-gprefixC-abind-keyC-asend-prefixuse|垂直分割面板,使用-水平分割面板#splitpanesusing|和绑定|split-window-hbind-split-window-vunbind'"'unbind%以更快地重新加载配置,使用前缀+r#重新加载配置文件(将文件位置更改为您要使用的tmux.conf)绑定r源-file~/.tmux.conf\;display-message"Configreloaded..."要更快地切换面板,请使用Alt键和箭头键切换面板#switchpanesusingAlt-arrowwithoutprefixbind-nM-Leftselect-pane-Lbind-nM-Rightselect-pane-Rbind-nM-Upselect-pane-Ubind-nM-Downselect-pane-D打开鼠标模式(不一定需要)#Enablemousemode(tmux2.1及以上)set-gmouseon停止自动重命名窗口,通过手动重命名,每个窗口可以执行不同的上下文别名创建一个dc别名,它的作用是当我们误输入cd时正确执行别名作为dcdc="cd"executehistory|awk'{$1="";printsubstr($0,2)}'|sort|uniq-c|sort-n|tail-n10获取前十个命令,尝试为它们创建别名.注意:此命令仅适用于Bash,如果您使用ZSH,请将history替换为history1.配置文件让我们帮助您了解有关配置文件的更多信息:为您的配置文件创建一个新文件夹,并设置版本控制至少添加其中有一个配置文件,假设您的shell中有一些自定义设置(从设置$PS1开始)。建立一种在新设备上快速安装和配置的方法(无需手动步骤)。最简单的方法是为每个文件编写一个使用ln-s的shell脚本,或者您可以使用专用工具在新虚拟机上测试安装脚本。将所有现有配置文件移动到项目存储库中。将项目发布到GitHub。我把我的tmux、vim和zsh的配置文件上传到了GitHub,欢迎基于此修改:https://github.com/chris-algo/dotfiles。广告时间如果喜欢我的文章,请给我点赞关注!也欢迎关注我的公众号:算法哥Chris。