我面临的一个问题是,我有一组包含大量数据的服务器。每个主机都运行特定进程 p1 的多个实例,这会并行与其他主机建立多个 scp 连接以获取必须处理的数据。这反过来会给这些主机带来很大的负载,很多时候它们会宕机。
我正在寻找可以限制可以在单个主机上运行的并发 scp 进程数量的方法。
大多数链接都指向 /etc/ssh/sshd_config 中的 MaxStartup 和 MaxSessions 设置,这些设置更多地与限制在任何给定点等可以创建/启动的 ssh 会话数量有关。
scp 是否有可以在此处使用的特定配置文件?或者是否有系统级别的方法来限制一次可以同时运行的特定进程/命令的实例数量?
答案1
scp
本身没有这样的功能。与GNUparallel
你可以使用sem
命令(来自信号) 任意限制并发进程:
sem --id scp -j 50 scp ...
对于以相同的 启动的所有进程--id
,这应用了 50 个并发实例的限制。尝试启动第 51 个进程将(无限期地)等待,直到其他进程之一退出。添加--fg
以将进程保持在前台(默认情况下是在后台运行它,但这与 shell 后台进程的行为不太一样)。
请注意,状态存储在中,${HOME}/.parallel/
因此如果您有多个用户使用 ,则这不会像希望的那样工作scp
,您可能需要为每个用户设置一个较低的限制。 (调用时也应该可以覆盖HOME
环境变量sem
,确保umask
允许组写入,并修改权限以便它们共享状态,但我还没有对此进行大量测试,YMMV。)
parallel
仅需要perl
几个标准模块。
您还可以考虑使用scp -l N
其中 N 是以 kBps 为单位的传输限制,选择特定的密码(为了速度,取决于您所需的安全性),或禁用压缩(特别是在数据已经压缩的情况下)以进一步减少对 CPU 的影响。
对于scp
,ssh 实际上是一个管道,并且scp
在每一端运行一个实例(接收端使用未记录的-t
选项运行)。关于MaxSessions
,这不会有帮助,“会话”是通过单个 SSH 连接进行复用的。尽管存在大量相反的错误信息,但MaxSessions
限制仅有的每个 TCP 连接的会话复用,没有任何其他限制。
PAM 模块pam_limits
支持限制并发登录,因此如果 OpenSSH 是使用 PAM 构建的,并且usePAM yes
存在于sshd_config
您可以通过用户名、组成员身份(等等)设置限制。然后您可以在 中设置硬性maxlogins
限制登录/etc/security/limits.conf
。然而这会计算每个用户的所有登录次数,而不仅仅是使用 justssh
和 not just 的新登录次数scp
,因此除非您有专用的用户 ID,否则您可能会遇到麻烦scp
。启用后,它也将适用于交互式 ssh 会话。解决这个问题的一种方法是复制或符号链接sshd
二进制文件,然后调用它,sshd-scp
然后您可以使用单独的 PAM 配置文件,即/etc/pam.d/sshd-scp
(OpenSSH 调用pam_start()
的“服务名称”设置为它被调用的二进制文件的名称)。您需要在单独的端口(或 IP)上运行它,并且使用单独的端口sshd_config
可能也是一个好主意。如果您实现此操作,那么scp
当达到限制时将会失败(退出代码 254),因此您必须在传输过程中处理该问题。
(其他选项包括ionice
和cpulimit
,这些可能会导致scp
会话超时或长时间挂起,从而导致更多问题。)
做类似事情的老式方法是使用atd
and batch
,但这不提供并发调整,它会在负载低于特定阈值时排队并启动进程。一个新的变体是任务假脱机程序支持以更可配置的顺序/并行方式排队和运行作业,并支持运行时重新配置(例如更改排队作业和并发设置),尽管它本身不提供负载或 CPU 相关控制。