问题描述
今天在使用homebrew
安装tmux
的时候,由于网络原因所以进度很慢,所以直接Ctrl+z挂起了终端的进程。随后想要再次运行brew install tmux
的时候产生了如下错误:
Error: Operation already in progress for tmux
Another active Homebrew process is already using tmux.
Please wait for it to finish or terminate it to continue.
解决方案
根据github
上的介绍,主要解决方法分两步:
- 删除
homebrew
的锁文件:
rm $(brew --cache)/Formula/*.brewing
- 终止
homebrew
的ruby
进程:
重启计算机或者在top
命令中找到ruby
,kill
掉这个进程。
原理
homebrew锁机制
homebrew
在安装文件的时候会为针对每一个模块产生一个安装锁文件。这种文件我们平常的脚本中也经常用到,就不赘述了。这个锁文件在$(brew --cache)/Formula
文件夹中,后缀名是brewing
。因此首先我们需要删除相关的这个文件。
对于第二点,有一些进程会通过设置避免被终端传来的hangup
信号中断。而进程中已经持有了锁的状态,因此我们需要手动终结这个进程。这样在下一次创建进程的时候就会根据锁文件的状态来判断锁状态了。
我们可以做个实验:
- 运行一个
brew
的命令。 - 在过程中使用
Ctrl+z
挂起。
1.png - 使用
htop
检测进程运行情况。
2.png
可以看出这条进程并没有被终结。所以我们需要去手动kill
一下。
长进程防止被中断
如本次遇到的情况一般,有时候我们也可能会需要使用这种机制避免终端的断开导致进程被中断。比如在远程连接执行一个时间很长的脚本的时候。这时候我们可以使用一些机制来防止终端的hangup
信号传递给脚本中断进程。
nohup
nohup
的用途就是让提交的命令忽略 hangup
信号。
NOHUP(1) BSD General Commands Manual NOHUP(1)
NAME
nohup -- invoke a utility immune to hangups
SYNOPSIS
nohup [--] utility [arguments]
DESCRIPTION
The nohup utility invokes utility with its arguments and at this time sets the signal SIGHUP to be ignored. If the standard output is a terminal, the standard output is appended to the file nohup.out in the current directory. If standard
error is a terminal, it is directed to the same place as the standard output.
Some shells may provide a builtin nohup command which is similar or identical to this utility. Consult the builtin(1) manual page.
使用方法如:
nohup cat test.txt
setsid
nohup
通过忽略 HUP
信号来使我们的进程避免中途被中断。但如果我们换个角度思考,如果我们的进程不属于接受 HUP
信号的终端的子进程,那么自然也就不会受到 HUP
信号的影响了。
&
使用形如:
(tail -f test.txt &)
的语法结构一样可以达成类似setsid
命令的效果。都是将这个进程的父进程改成其他的进程,比如init
进程。
disown
用disown -h jobspec来使某个作业忽略HUP信号。
用disown -ah 来使所有的作业都忽略HUP信号。
用disown -rh 来使正在运行的作业忽略HUP信号。
当使用过 disown 之后,会将把目标作业从作业列表中移除,我们将不能再使用jobs来查看它,但是依然能够用ps -ef查找到它。
但是还有一个问题,这种方法的操作对象是作业,如果我们在运行命令时在结尾加了"&"来使它成为一个作业并在后台运行,那么就万事大吉了,我们可以通过jobs命令来得到所有作业的列表。但是如果并没有把当前命令作为作业来运行,如何才能得到它的作业号呢?答案就是用 CTRL-z(按住Ctrl键的同时按住z键)了!
CTRL-z 的用途就是将当前进程挂起(Suspend),然后我们就可以用jobs命令来查询它的作业号,再用bg jobspec来将它放入后台并继续运行。需要注意的是,如果挂起会影响当前进程的运行结果,请慎用此方法。
参考文章:
网友评论