【小白笔记】如何在云服务器上高效运行Python程序并实时监控
如何在云服务器上高效运行Python程序并实时监控
最近在服务器上跑一个任务,需要让程序在后台持续运行,即使我断开SSH连接也能正常工作。
1. 问题:如何查看正在后台运行的程序?
我一开始用的是最基础的 ps aux 命令。它能列出所有正在运行的进程,然后我通过 grep 过滤出我需要的Python程序。
ps aux | grep "python /data/Avatar/Wan2.2/generate.py"
但发现一个问题:当我尝试这么做时,终端返回的只有 grep 命令本身,这说明我的程序根本没有在运行。
详细解释一下 ps aux 和 grep 这两个命令的英文含义和具体作用。这部分内容通常是Linux系统管理员和开发者必备的知识。
ps aux
ps 是 Process Status 的缩写,意思是“进程状态”。它的主要作用是显示当前系统中的进程信息。
aux 是三个不同的选项(option),它们通常组合在一起使用,但每个都有特定的含义:
a:代表 all,意思是“所有”。这个选项会显示所有终端上的进程,而不仅仅是当前终端的进程。u:代表 user-oriented format,意思是“用户导向格式”。它会以更友好的方式展示进程信息,比如显示进程的CPU和内存使用率、启动该进程的用户名等。x:代表 no-controlling-tty,意思是“没有控制终端”。这个选项会显示没有关联终端的进程,这些进程通常是系统在后台运行的服务或守护进程(daemon)。
所以,ps aux 的整体意思就是:以用户友好的格式,列出系统上所有进程(包括有终端的和没有终端的)的详细状态。
x 代表 no-controlling-tty 的设计,源于 Unix 系统中进程与终端之间的关系。
x 选项的由来
在 Unix/Linux 系统中,一个进程通常会与一个**控制终端(controlling terminal)**关联。这个终端是进程的输入来源和输出目的地。
- 前台进程:当你直接在终端中运行一个程序(比如
ls),这个程序就是前台进程,它会和你的终端紧密相连。 - 后台进程:而有些进程,比如系统服务(例如网站服务器、数据库),它们是在系统启动时自动运行的,没有直接与任何终端相连。这类进程被称为守护进程(daemon),它们在后台默默运行,不依赖用户的终端。
ps 命令的早期版本,默认只显示那些与当前终端关联的进程。这意味着,如果你想查看那些在后台独立运行的系统服务,常规的 ps 命令是看不到的。
为了解决这个问题,开发者添加了 x 选项。
x选项让ps命令的行为发生了变化,它会“忽略”进程是否有控制终端(no-controlling-tty)这个条件。- 有了
x选项,ps就能显示所有进程,包括那些没有终端的守护进程。
因此,当你使用 ps aux 时,你看到的不只是你当前终端里运行的程序,还有系统里所有正在后台默默工作的进程。这个选项的设计正是为了让你能全面地掌握系统的运行状态。
tty 是 teletypewriter(电传打字机)的缩写。在现代的 Linux/Unix 系统中,它通常指的是终端(terminal)。
这个词的起源非常有意思,它直接反映了计算机发展的历史。
tty 的词源
在计算机早期,人们使用一种叫做电传打字机的设备与计算机进行交互。这种设备类似于一台带键盘和打印机的打字机,用户在键盘上输入命令,电传打字机将这些命令转换成电信号发送给计算机,然后计算机将结果转换成电信号发回,通过打印机把结果打印在纸上。
所以,“tty” 这个词最初就是指这种物理设备。
tty 在现代 Linux/Unix 中的含义
虽然电传打字机早已被键盘和显示器取代,但 tty 这个术语在操作系统中被保留了下来,用来代表各种形式的终端设备。
在 Linux 系统中,tty 可以指代以下几种类型:
-
虚拟控制台(Virtual Consoles):当你没有启动图形界面时,按下
Ctrl + Alt + F1到F6,你会进入不同的全屏文本模式终端,它们就是虚拟控制台,也叫tty1、tty2等。 -
伪终端(Pseudo-terminals):当你通过 SSH 远程登录云服务器,或者在图形界面中打开一个终端模拟器(比如 GNOME Terminal, Konsole, iTerm2)时,你所使用的就是一种伪终端,通常命名为
pts/0、pts/1等。这里的pts就是 Pseudo-terminal Slave 的缩写。
简而言之,tty 是 Linux/Unix 中一个通用的概念,用来表示你与操作系统内核进行交互的接口。无论是直接连接的物理终端,还是远程登录或终端模拟器创建的虚拟终端,它们本质上都是 tty 的现代形式。
grep
grep 的英文全称是 Global Regular Expression Print,意思是“全局正则表达式打印”。这个名字听起来有点复杂,但它的功能其实很直观:在文本中搜索你指定的模式,并把匹配的行打印出来。
Global:全局。它会搜索整个输入。Regular Expression:正则表达式。虽然这里你用的是简单的文本字符串,但grep支持使用更复杂的模式(正则表达式)进行搜索。Print:打印。它会把匹配到的那一行内容打印到屏幕上。
在你的命令 ps aux | grep "python /data/Avatar/Wan2.2/generate.py" 中,grep 的作用就是:
- 接收
ps aux命令的输出(通过|管道符)。 - 在这些输出中,逐行搜索是否包含
"python /data/Avatar/Wan2.2/generate.py"这个字符串。 - 如果找到了,就把包含这个字符串的整行内容显示出来。
简而言之,grep 在这里的作用就像一个过滤器,它从一堆杂乱的进程信息中,为你精准地找出了你想要的特定程序。
2. 解决方案:使用 nohup 和 &
为了让程序在我关闭终端后也能继续运行,我需要用到 nohup 命令。
nohup(no hang up):这个命令可以防止程序在用户退出终端时被“挂断”(也就是停止)。&:这个符号非常关键,它能将命令放到后台运行,这样我就可以继续在终端中输入其他命令,而不用等待程序结束。
结合这两点,我构建了我的完整命令:
nohup CUDA_VISIBLE_DEVICES=3 PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True python /data/Avatar/Wan2.2/generate.py ... > program_output.log 2>&1 &
这条命令有点长,我来拆解一下:
nohup ... &:这是将命令放到后台运行并防止它停止的框架。CUDA_VISIBLE_DEVICES=3:这是一个环境变量,作用是告诉程序,这台机器上虽然可能有多个GPU,但它只能使用编号为3的那一块。这对于防止资源冲突非常重要。PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True:这是PyTorch的环境变量,用于优化GPU显存管理。它告诉PyTorch的内存分配器,如果需要更多内存,可以尝试扩展已有的内存块,这有助于防止显存溢出(OOM)。> program_output.log 2>&1:这是重定向操作。>将标准输出(STDOUT)重定向到program_output.log文件。2>&1则更进一步,将标准错误输出(STDERR)也重定向到同一个地方。这样,所有日志和错误信息都会被统一保存到这个文件中,方便我日后排查问题。
3. 实时监控程序运行状态
程序在后台运行后,我怎么知道它进行到哪里了呢?答案就在我之前重定向的日志文件里。
我可以使用 tail 命令来实时查看日志文件的更新:
tail -f program_output.log
tail:这个命令可以显示文件的末尾内容。-f:这个参数是"follow"的缩写,它会持续监控文件,只要有新内容写入,就会立即显示在终端上。
通过这个命令,我就可以实时看到程序的每一步输出,比如模型加载进度、生成帧数等等,就像程序在前台运行一样。
4. 最终解决的坑:注意命令格式
我在执行 nohup 命令时,曾因为不小心换行,导致终端把 CUDA_VISIBLE_DEVICES=3 当成了一个独立的命令去执行,从而报错 No such file or directory。
正确的做法是,确保将所有环境变量、程序命令和重定向操作符都写在同一行,不要有任何换行符。
如果你也遇到类似问题,可以尝试将环境变量单独 export 出来,然后再运行主程序,这样会更保险:
export CUDA_VISIBLE_DEVICES=3export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:Truenohup python /data/Avatar/Wan2.2/generate.py ... > program_output.log 2>&1 &
这个方法非常有效,而且 export 的环境变量只对当前终端会话生效,不会影响服务器上的其他进程或用户。如果你需要在另一块GPU上运行新任务,只需在新终端中为它指定不同的设备编号,它们之间不会产生冲突。
更多推荐



所有评论(0)