让服务器后台下载视频合集(后台运行命令)

986 阅读3分钟

需求

网络上有一些很好的课程合集,然而受到版权限制,有时候会被封禁,于是最好的办法就是自己下载下来。

这里采用 you-get 在服务器上挂载下载(相当于离线下载)。

问题

使用 ssh 连接上服务器之后就可以下载了,然而每次断开 ssh 连接之后,下载会自动停止,为什么?

答:当用户注销(logout)或者网络断开时,终端会收到 HUP(hangup)信号从而关闭其所有子进程。

因此,我们的解决办法就有两种途径:要么让进程忽略 HUP 信号,要么让进程运行在新的会话里从而成为不属于此终端的子进程。

解决:nohup/setsid/&

nohup you-get https://www.bilibili.com/video/av52118083 --playlist &  
# [1] 21999
# nohup: ignoring input and appending output to 'nohup.out'

jobs
# [1]+  Running                 nohup you-get https://www.bilibili.com/video/av52118083 --playlist &

只需在要处理的命令前加上 nohup 即可,标准输出和标准错误缺省会被重定向到 nohup.out 文件中。一般我们可在结尾加上"&"来将命令同时放入后台运行。

# 1
nohup - run a command immune to hangups, with output to a non-tty
 
SYNOPSIS
       nohup COMMAND [ARG]...
       nohup OPTION
 
DESCRIPTION
       Run COMMAND, ignoring hangup signals.
 
# 2
setsid - run a program in a new session
 
SYNOPSIS
       setsid program [ arg ... ]
 
DESCRIPTION
       setsid runs a program in a new session.

总结

# 方式一: nohup,忽略 hungup 信号
nohup ping www.ibm.com &
# 方式二:运行在新会话中,父 ID(PPID)为1(即为 init 进程 ID),并不是当前终端的进程 ID
setsid ping www.ibm.com
# 方式二
(ping www.ibm.com &) # 将一个或多个命名包含在“()”中就能让这些命令在子 shell 中运行中,加上 & 之后,新提交的进程的父 ID(PPID)为1(init 进程的 PID),并不是当前终端的进程 ID

补救?

我们已经知道,如果事先在命令前加上 nohup 或者 setsid 就可以避免 HUP 信号的影响。但是如果我们未加任何处理就已经提交了命令,该如何补救才能让它避免 HUP 信号的影响呢?

只能通过作业调度和 disown 来解决这个问题了。

disown [-ar] [-h] [jobspec ...]
    Without options, each jobspec is  removed  from  the  table  of
    active  jobs.   If  the -h option is given, each jobspec is not
    removed from the table, but is marked so  that  SIGHUP  is  not
    sent  to the job if the shell receives a SIGHUP.  If no jobspec
    is present, and neither the -a nor the -r option  is  supplied,
    the  current  job  is  used.  If no jobspec is supplied, the -a
    option means to remove or mark all jobs; the -r option  without
    a  jobspec  argument  restricts operation to running jobs.  The
    return value is 0 unless a jobspec does  not  specify  a  valid
    job.
  • 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来将它放入后台并继续运行。需要注意的是,如果挂起会影响当前进程的运行结果,请慎用此方法。

拓展阅读/参考

Linux 技巧:让进程在后台运行更可靠的几种方法


dfface 的版权声明:所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处,严禁商业用途!