如何在 运行 时更改一系列 bash 命令?

how to change a sequence of bash commands while running?

假设我想按顺序 运行 两个 python 脚本。我目前的解决方案是编写一个 bash run.sh 脚本,其中可以包含如下内容:

python foo.py
python bar.py

现在假设在终端中执行 ./run.sh 命令后 foo.py 为 运行ning(bar.py 尚未启动),我想运行baz.py(在执行./run.sh命令后创建的)而不是bar.py。 run.sh 脚本现在看起来像这样:

python foo.py
python baz.py

那么我的问题是:这可能吗?澄清一下:有没有办法即时修改命令行序列?此序列不必包含在 bash 文件中,并且可能涉及一些我不知道的 workflow/pipeline 管理程序。 主要目标是拥有一个我可以即时更改的动态进程列表。

我建议为此使用 python 解决方案。使用线程,您可以 运行 “并行”处理事物。我制作了一个 run.py 文件,然后可以通过 bash 成为 运行。这只是原则。您可以将 'run.py' 文件中的输入更改为适合您的目的。

第一个线程启动 run1(),然后通过导入启动 test1.py。当发生这种情况时,第二个线程“并行”开始 run2 并要求您提供输入。如果输入是 2 test2.py 启动,如果输入是 3 test3.py 启动 运行 与 test1.py “并行”,如果尚未完成。

# test1.py
import time
print("This is test1.py running")
time.sleep(10)
print("This is test1.py finishing")
# test2.py
import time
print("This is test2.py running")
time.sleep(10)
print("This is test2.py finishing")
# test3.py
import time
print("This is test3.py running")
time.sleep(10)
print("This is test3.py finishing")
# run.py
import threading

def run1():
    import test1
    
def run2():
    i = int(input("2 or 3: "))
    if i == 2:
        import test2
    elif i == 3:
        import test3
    else:
        print("jumped over 2 and 3")
        
t1 = threading.Thread(target=run1)
t2 = threading.Thread(target=run2)

t1.start()
t2.start()

t1.join()
t2.join()

让您的 Python 脚本 foo.py 将您想要的脚本的名称写入文件 ./.script,如下所示:

# imports


with open('./.script.py', 'w') as f:
    f.write('python bar.py')

# do stuff

if condition:
    with open('./.script.py', 'w'):
        f.write('python baz.py')

那么你的脚本可以看起来像

#!/bin/bash
python foo.py
`cat .script`

无需即时修改。

保持简单。

#! /bin/bash

python3 foo.py
second=$(< second)
python3 "${second:-bar.py}"

如果您将 baz.py 写入 second 文件(即使您从 foo.py 写入它),那么 run.sh 将执行它而不是 bar.py

使用数据库中的动态任务

# create sqlite db with your tasks
$ sqlite3 mydb.sql
sqlite> create table tasks (id integer primary key, name text);
sqlite> insert into tasks values (1,"foo.py");
sqlite> insert into tasks values (2,"bar.py");
sqlite> select * from tasks;
1|foo.py
2|bar.py
run.sh
#!/bin/bash


MYDB="./mydb.sql"

execTask(){
   local id=
   task=$(sqlite3 $MYDB "select name from tasks where id = ")
   [ -z "$task" ] && { echo "no task found for id $id" ; return 1; }
   echo "exec task $task"
   python3 $task
}


execTask 1

execTask 2

输出:

$ bash run.sh
exec task foo.py
exec task baz.py

从控制台或其他脚本更新任务table

$ sqlite3 mydb.sql "update tasks set name = 'baz.py' where id = 2" 

我使用 slurm 解决了我自己的问题。我发现我的问题与此类似 post: What is the simplest queue job manager for linux?

正如我在问题结尾所说的那样,我需要一个作业管理器工具(因此比 over-simplified 示例中介绍的简单脚本的执行更通用)。我知道 slurm,但我想看看是否有人知道可以在个人计算机上使用的更简单的东西(涉及 bash 或其他软件,而不是经历我在安装 slurm 时遇到的所有困难)。

如果有人想在他们的个人笔记本电脑上使用 slurm(我用 Ubuntu 20.04 测试过),我建议关注以下博客 posts:

最难的部分是slurm.conf创作(https://slurm.schedmd.com/configurator.html)。为了对我自己的安装过程进行反馈,我建议:

  • 以 root 用户身份进行安装,
  • 将 SlurmUser 设置为 root
  • 将 SlurmctldHost 和 NodeName 设置为您计算机的名称
  • 让其他参数默认

感谢@Zorgoth、@Diego Torres Milano、@ufopilot 和@perperam 提出的建议。