You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SIGUSR1信号在tar中异常失效:进程被终止而非返回进度

问题原因及解决方法

核心原因分析

1. shell=True导致信号误发给shell进程

如果你的Python代码用shell=True启动tar,实际运行的是shell进程(bash/sh),tar只是shell的子进程。此时调用process.send_signal()或os.killpg()会把信号发给shell,而shell默认没有处理SIGUSR1的逻辑,会直接终止。shell终止时会向子进程发送SIGHUP信号,导致tar也跟着终止(返回码-10对应SIGUSR1,实际是shell被该信号杀死)。

而用subprocess.Popen(["pkill", "-SIGUSR1", "tar"])时,信号是直接匹配tar进程发送的,tar能正确识别并处理,不会终止。

2. 环境变量缺失导致信号处理崩溃

如果Python进程运行在非终端环境(比如后台脚本),子进程的TERM环境变量可能缺失。GNU tar在收到SIGUSR1输出进度时,需要TERM确定终端输出格式,缺失该变量可能导致tar崩溃,表现为收到信号后直接终止。

3. 信号发送时机过早

如果在tar完成初始化、安装好SIGUSR1处理函数之前发送信号,tar会触发默认的信号处理逻辑而终止。

解决方法

方法1:避免使用shell=True,直接启动tar进程

用列表形式传递命令参数,此时process.pid就是tar进程的PID,信号会直接发送给tar:

import subprocess
import signal
import time

# 直接启动tar进程,无需shell
process = subprocess.Popen(["tar", "-xpf", "archive.tar", "--totals=SIGUSR1", "./blah"])
time.sleep(1)  # 等待tar完成初始化
process.send_signal(signal.SIGUSR1)
# tar会输出进度到stderr,进程不会终止

方法2:若必须用shell=True,找到tar的真实PID再发信号

通过父进程PID(shell的PID)找到tar的PID,直接向tar发送信号:

import subprocess
import signal
import time
import os

process = subprocess.Popen("tar -xpf archive.tar --totals=SIGUSR1 ./blah", shell=True)
time.sleep(1)
# 获取shell的子进程(即tar)的PID
tar_pid = int(subprocess.check_output(["pgrep", "-P", str(process.pid)]).strip())
os.kill(tar_pid, signal.SIGUSR1)

方法3:补充缺失的环境变量

给子进程设置TERM环境变量,确保tar能正常输出进度:

import subprocess
import signal
import time
import os

env = os.environ.copy()
env["TERM"] = "xterm"  # 模拟终端环境
process = subprocess.Popen(["tar", "-xpf", "archive.tar", "--totals=SIGUSR1", "./blah"], env=env)
time.sleep(1)
process.send_signal(signal.SIGUSR1)

内容的提问来源于stack exchange,提问作者Xevion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 19:54:56