如何在队列中运行命令

Svi*_*ish 49 unix batch queue command-line process

我需要将各种文件复制到各种文件夹中。我可以将所有复制命令添加到 bash 脚本中,然后运行它,但是如果我想向该复制“队列”添加更多命令,我必须等到它完成。

有没有办法可以将命令作为队列运行,并在运行时向该队列添加更多命令?

以不同的方式解释,我想开始一个长时间运行的任务。在运行时,我想启动另一个在第一个完成之前实际上不会启动的。然后在最后一个之后添加另一个,依此类推。这有可能吗?

Vor*_*ico 29

附加&到您的命令的末尾以将其发送到后台,然后wait在运行下一个之前就可以了。例如:

$ command1 &
$ wait; command2 &
$ wait; command3 &
$ ...
Run Code Online (Sandbox Code Playgroud)

  • 如果您在此期间改变了对这些命令中的任何一个的想法,可以做些什么来中止“等待”?它似乎不受我所有杀戮的影响。 (3认同)
  • 好极了!当您开始执行某些操作然后查看 stackoverflow 以寻找一种在其后进行排队的方法时,这种语法非常棒 (2认同)

Gil*_*il' 28

at实用程序以在指定时间运行命令而闻名,它还具有队列功能,可以要求立即开始运行命令。它从标准输入读取要运行的命令。

echo 'command1 --option arg1 arg2' | at -q myqueue now
echo 'command2 ...' | at -q myqueue now
Run Code Online (Sandbox Code Playgroud)

batch命令等效于at -q b -m now(-m意味着命令输出,如果有的话,将邮寄给你,就像 cron 一样)。并非所有 Unix 变体都支持队列名称 ( -q myqueue);您可能仅限于一个名为b. Linuxat仅限于单字母的队列名称。

  • 至少在 linux 上,这似乎不会等待上一个命令完成。 (3认同)

小智 12

Brad 和 Mankoff 的解决方案都是很好的建议。另一个类似于两者组合的方法是使用GNU Screen来实现您的队列。这样做的好处是可以在后台运行,你可以随时查看它,排队新命令只是将它们粘贴到缓冲区中以便在前一个命令退出后执行。

第一次运行:

$ screen -d -m -S queue
Run Code Online (Sandbox Code Playgroud)

(顺便说一句,现在是玩一些很棒的.screenrc 文件的好时机)

这将为您命名队列生成一个后台屏幕会话。

现在,将任意数量的命令排入队列:

screen -S queue -X stuff "echo first; sleep 4; echo second^M"
Run Code Online (Sandbox Code Playgroud)

我在上面做了多个命令只是为了测试。您的用例可能看起来更像:

screen -S queue -X stuff "echo first^M"
screen -S queue -X stuff "echo second^M"
Run Code Online (Sandbox Code Playgroud)

请注意,上面我行中的“^M”是一种获取嵌入换行符的方法,稍后将在 screen 将其填充到现有 bash shell 后解释该换行符。使用“CTL-V”来获取该序列。

制作一些简单的 shell 脚本来自动化并排队命令会很容易。然后,每当您想检查后台队列的状态时,您都可以通过以下方式重新附加:

screen -S queue -r
Run Code Online (Sandbox Code Playgroud)

从技术上讲,你甚至不需要命名你的屏幕会话,它会工作得很好,但是一旦你迷上了它,无论如何你都会想让它一直运行。;-)

当然,如果您这样做,另一种好方法是将当前窗口之一命名为“队列”并使用:

screen -S queue -p queue -X stuff "command"
Run Code Online (Sandbox Code Playgroud)


hol*_*lmb 10

对于您所描述的用例,我已经成功使用了一个实用程序。最近,我将我的主要笔记本电脑移到了新硬件上,这涉及将一些文件移到 NAS,而将其余文件移到新机器上。

我就是这样做的。

  1. 设置所有涉及网络连接的机器,以便它们可以相互访问。

  2. 在您从中移动文件的机器(以下称为源机器)上,安装 rsyncapt-get install rsync和 secret-sauce Task Spooler(网站http://vicerveza.homeunix.net/~viric/soft/ts/)。如果您使用的是 Debian,则软件包名称为tsis task-spooler,并且可执行文件被重命名为tsp以避免与软件包中的ts可执行文件发生名称冲突moreutils。从网站链接的 Debian 软件包可以完美地安装在 Ubuntudpkg -i task-spooler_0.7.3-1_amd64.deb或类似软件上。

  3. 还要确保所有机器都安装了 SSH apt-get install openssh-server。在源机器上,您需要设置 SSH 以允许无密码登录目标机器。最常用的方法是使用公钥身份验证ssh-agent(有关示例,请参阅https://www.google.se/search?q=ssh+public+key+authentication),但我有时会使用更简单的方法以及密码认证。将以下内容添加到您的 SSH 客户端配置(~/.ssh/config/etc/ssh/ssh_config):

    Host *
         ControlMaster auto
         ControlPath ~/.ssh/master-%r@%h:%p
    
    Run Code Online (Sandbox Code Playgroud)

    然后在源机器上打开一个终端,用 登录ssh target1,像往常一样进行身份验证,然后让这个终端保持打开状态。请注意,有一个名为 的套接字文件~/.ssh/master-user@target1:22,该文件将保持经过身份验证的主会话打开并允许后续无密码连接user(只要连接使用相同的目标主机名和端口)。

    此时,您需要验证是否可以登录,而不会提示您对目标计算机进行身份验证。

  4. 现在ts rsync -ave ssh bigfile user@target1:为单个文件或ts rsync -ave ssh bigdir user@target1:目录运行。对于 rsync,重要的是不要在目录中包含尾部斜杠(bigdir与 相比bigdir/),否则 rsync 会假设您的意思是bigdir/*大多数其他工具中的等效斜杠。

    任务假脱机程序将返回提示并让您连续排队许多这些命令。ts不带参数检查运行队列。

任务假脱机程序具有许多功能,例如重新排列运行队列、仅在另一个作业成功运行时才运行特定作业等。查看帮助ts -h。我有时会在运行时检查命令输出ts -c

还有其他方法可以做到这一点,但对于您的用例,它们都包括任务假脱机程序。我选择通过 SSH 使用 rsync 来保留文件时间戳,而通过 SMB 复制则不会。


小智 0

我能想到的最黑客的方法是使用 /tmp 中的简单锁定文件来维护队列“状态”。当 file1.sh 执行 cp 命令时,它将在 /tmp 中保留一个锁定文件(或硬链接)。完成后,删除该文件。所有其他脚本都必须在 /tmp 中查找具有您选择的命名方案的锁定文件。当然,这会遇到各种失败,但设置起来很简单,并且完全可以在 bash 中完成。