调用 rsync 的子进程在可能的缓冲区填充后挂起
subprocess calling rsync hangs after possible buffer fill
[root@devdbadmin bin]# uname -a
Linux devdbadmin 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20 20:32:50 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
[root@devdbadmin bin]# python3.5 --version
Python 3.5.0
我遇到了一个问题,我一直未能成功调试,我正在尝试通过子进程和 python 运行 多个 rsync 命令。我花了很多时间阅读所有的陷阱,但一直没能弄清楚 运行。我不关心 rsync 的输出,也不关心 stderr/stdout。我只是在寻找成功或失败的 return 代码。发生的事情是第一个 rsync 会工作,偶尔第二个命令会工作,在任何时候 child 进程都会间歇性地停止,根据 strace 显示为超时:
select(4, NULL, [3], [3], {60, 0}) = 0 (Timeout)
我已将其缩小到子进程,因为我能够 运行 shell 中的命令没有任何问题。我认为缓冲区正在填充并导致 child 死锁或等待。根据我阅读的手册:
Warning
This will deadlock when using stdout=PIPE and/or stderr=PIPE and the
child process generates enough output to a pipe such that it blocks
waiting for the OS pipe buffer to accept more data. Use communicate()
to avoid that
事实是,我没有在我的子进程命令中使用管道,所以我很困惑。我尝试使用 -u 调用 python 以取消缓冲,并且我尝试使用 rsync -stbuf=L 作为行。这是代码的相关部分。
subfolders = ['7/centosplus/x86_64',
'7/updates/x86_64',
'7/x86_64',
'epel/7/x86_64',
'remi/x86_64',
'php56/x86_64',
'nginx']
princeton_commands = [['rsync -az rsync://mirror.math.princeton.edu/pub/centos/7/os/x86_64/ 7/x86_64/'],
['rsync -az rsync://mirror.math.princeton.edu/pub/centos/7/updates/x86_64/ 7/updates/x86_64/'],
['rsync -az rsync://mirror.math.princeton.edu/pub/centos/7/centosplus/x86_64/ 7/centosplus/x86_64/']]
def makefolders(root_dir, subfolders):
concat_path = functools.partial(os.path.join, root_dir)
dir_list = list(map(concat_path, subfolders))
logger.info('CREATING DIRECTORIES: %s' % dir_list)
for dirs in dir_list:
os.makedirs(dirs)
def execute_jobs(cmd):
try:
subprocess.run(cmds,shell=True, check=True)
logger.info('rsync Success: %s' % cmd)
except subprocess.CalledProcessError as e:
logger.critical('%s FATAL: Command failed with error: %s' % (cmd,e))
def main():
if os.path.exists(root_dir):
logger.critical('PATH EXISTS, manually run [ rm -rf %s ] to proceed...' % root_dir)
sys.exit(1)
makefolders(root_dir, subfolders)
os.chdir(root_dir)
for cmds in princeton_commands:
execute_jobs(cmds)
main()
我知道 linux 有一个 pipr 缓冲区,但是我没有在我的 rsync 命令上使用 -v verbose 所以我没有得到太多可以填充这个缓冲区的输出,我也没有使用管道在前面提到的子流程中。我正在使用 free 查看内存是否已满,但我没有看到任何相关内容。
重要的是,我已经尝试了多个镜像主机,认为我被限制或阻止了,但是 rsync 将在我尝试的任何主机上停止,一旦它运行到一半。
编辑:
Here is the strace and lsof of the process stuck:
root 29195 8.6 0.0 117488 2084 pts/0 S 10:47 1:54 | | \_ rsync -az rsync://mirror.math.princeton.edu/pub/centos/7/updates/x86_64/ 7/updates/x86_64/
[root@devdbadmin bin]# strace -p 29195
strace: Process 29195 attached
select(4, [3], [], [3], {52, 716623}) = 0 (Timeout)
select(4, [3], [], [3], {60, 0}^Cstrace: Process 29195 detached
[root@devdbadmin bin]# lsof -p 29195 -ad 4,3
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rsync 29195 root 3u IPv4 1686385 0t0 TCP devdbadmin.afs:40500->mirror.math.princeton.edu:rsync (ESTABLISHED)
rsync 29195 root 4u REG 253,3 786432 10755679 /u01/repo/monthly/CentOS7/2018-02/7/updates/x86_64/drpms/.python-perf-3.10.0-514.26.1.el7_3.10.0-693.5.2.el7.x86_64.drpm.g7XODd
在调试并学习了很多关于 strace/rsync、subprocess 的知识之后,我联系了官方镜像的一位管理员并解释了我的情况。他们要求我在凌晨 12 点到早上 8 点之间开始同步关闭时间。一旦这样做,rsyncs 就会正常完成。所以我认为问题是发送者 运行 没有 rsync 槽或资源来发送数据。 strace 输出显示它正在等待未获取数据的 fd。我希望这对任何人都有帮助,我希望有人可以通过查看我的 strace 来确认这一点。
[root@devdbadmin bin]# uname -a
Linux devdbadmin 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20 20:32:50 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
[root@devdbadmin bin]# python3.5 --version
Python 3.5.0
我遇到了一个问题,我一直未能成功调试,我正在尝试通过子进程和 python 运行 多个 rsync 命令。我花了很多时间阅读所有的陷阱,但一直没能弄清楚 运行。我不关心 rsync 的输出,也不关心 stderr/stdout。我只是在寻找成功或失败的 return 代码。发生的事情是第一个 rsync 会工作,偶尔第二个命令会工作,在任何时候 child 进程都会间歇性地停止,根据 strace 显示为超时:
select(4, NULL, [3], [3], {60, 0}) = 0 (Timeout)
我已将其缩小到子进程,因为我能够 运行 shell 中的命令没有任何问题。我认为缓冲区正在填充并导致 child 死锁或等待。根据我阅读的手册:
Warning
This will deadlock when using stdout=PIPE and/or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use communicate() to avoid that
事实是,我没有在我的子进程命令中使用管道,所以我很困惑。我尝试使用 -u 调用 python 以取消缓冲,并且我尝试使用 rsync -stbuf=L 作为行。这是代码的相关部分。
subfolders = ['7/centosplus/x86_64',
'7/updates/x86_64',
'7/x86_64',
'epel/7/x86_64',
'remi/x86_64',
'php56/x86_64',
'nginx']
princeton_commands = [['rsync -az rsync://mirror.math.princeton.edu/pub/centos/7/os/x86_64/ 7/x86_64/'],
['rsync -az rsync://mirror.math.princeton.edu/pub/centos/7/updates/x86_64/ 7/updates/x86_64/'],
['rsync -az rsync://mirror.math.princeton.edu/pub/centos/7/centosplus/x86_64/ 7/centosplus/x86_64/']]
def makefolders(root_dir, subfolders):
concat_path = functools.partial(os.path.join, root_dir)
dir_list = list(map(concat_path, subfolders))
logger.info('CREATING DIRECTORIES: %s' % dir_list)
for dirs in dir_list:
os.makedirs(dirs)
def execute_jobs(cmd):
try:
subprocess.run(cmds,shell=True, check=True)
logger.info('rsync Success: %s' % cmd)
except subprocess.CalledProcessError as e:
logger.critical('%s FATAL: Command failed with error: %s' % (cmd,e))
def main():
if os.path.exists(root_dir):
logger.critical('PATH EXISTS, manually run [ rm -rf %s ] to proceed...' % root_dir)
sys.exit(1)
makefolders(root_dir, subfolders)
os.chdir(root_dir)
for cmds in princeton_commands:
execute_jobs(cmds)
main()
我知道 linux 有一个 pipr 缓冲区,但是我没有在我的 rsync 命令上使用 -v verbose 所以我没有得到太多可以填充这个缓冲区的输出,我也没有使用管道在前面提到的子流程中。我正在使用 free 查看内存是否已满,但我没有看到任何相关内容。
重要的是,我已经尝试了多个镜像主机,认为我被限制或阻止了,但是 rsync 将在我尝试的任何主机上停止,一旦它运行到一半。
编辑:
Here is the strace and lsof of the process stuck:
root 29195 8.6 0.0 117488 2084 pts/0 S 10:47 1:54 | | \_ rsync -az rsync://mirror.math.princeton.edu/pub/centos/7/updates/x86_64/ 7/updates/x86_64/
[root@devdbadmin bin]# strace -p 29195
strace: Process 29195 attached
select(4, [3], [], [3], {52, 716623}) = 0 (Timeout)
select(4, [3], [], [3], {60, 0}^Cstrace: Process 29195 detached
[root@devdbadmin bin]# lsof -p 29195 -ad 4,3
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rsync 29195 root 3u IPv4 1686385 0t0 TCP devdbadmin.afs:40500->mirror.math.princeton.edu:rsync (ESTABLISHED)
rsync 29195 root 4u REG 253,3 786432 10755679 /u01/repo/monthly/CentOS7/2018-02/7/updates/x86_64/drpms/.python-perf-3.10.0-514.26.1.el7_3.10.0-693.5.2.el7.x86_64.drpm.g7XODd
在调试并学习了很多关于 strace/rsync、subprocess 的知识之后,我联系了官方镜像的一位管理员并解释了我的情况。他们要求我在凌晨 12 点到早上 8 点之间开始同步关闭时间。一旦这样做,rsyncs 就会正常完成。所以我认为问题是发送者 运行 没有 rsync 槽或资源来发送数据。 strace 输出显示它正在等待未获取数据的 fd。我希望这对任何人都有帮助,我希望有人可以通过查看我的 strace 来确认这一点。