如何使端口专用于特定的预定进程?

如何使端口专用于特定的预定进程?

我们有一个 XYZ 批处理流程,每天凌晨 2:00 启动。此 XYZ 配置为在端口 59070 上启动。完成后,此端口将成为开放端口。但最近我们遇到了一个问题,另一个进程正在使用 59070,当这个 XYZ 进程启动时,它无法运行。

作为解决方法,我们已将配置更新到不同的端口 59071 并正常运行该过程。我的疑问是,我们是否可以阻止此端口 59070 并确保没有其他进程使用它?我们使用的是 Solaris 10。

答案1

端口 59070 是临时端口- 一个可以用于出境任何进程的 TCP 连接。 (端口 59071 也是如此,所以这并不是一个很好的解决方法......)

在 Solaris 上,临时端口范围由以下方式设置tcp_smallest_anon_porttcp_largest_anon_port可调参数。默认范围是 32,768 到 65,535。该范围内的任何端口都可能正在使用中随时通过传出 TCP 连接。

正如 @Jeff Schaller 的回答所述,端口是按照先到先得的原则使用的,因此“保留”端口的唯一方法是始终将某些东西绑定到它。请注意,在该答案中,另一个进程可能会在杀死“端口保护程序”脚本和实际使用该端口的“正常”进程之间的时间内获取有问题的端口bind()。它不是可能,诚然,但这可能会发生。如果您的处理至关重要,我认为您需要担心这一点。

我建议不要使用临时端口和/或将你的进程配置为一直运行,或者用于inetadm配置自动运行您的进程的服务。这将导致inetd进程始终绑定到“您的”端口,从而有效地保留它供您使用。

答案2

除了自己主动使用端口之外,我不知道有什么方法可以阻止端口的使用。我提出的总体想法是将批处理更改为:

  1. 杀死“端口保护程序”脚本

  2. 运行正常的批处理

  3. 启动一个新的“端口保护程序”脚本

此解决方法将帮助防止恶意进程绑定到您想要的端口(进程可能会在步骤 1 和 2 之间或步骤 2 和 3 之间抢占端口),但它会不是防止批处理过程出现意外,即批处理过程似乎已结束但未释放端口(通过退出其所有进程)。

Perl 中的示例“端口保护程序”脚本如下:

#!/usr/bin/env perl
# listens on the given port
use strict;
use IO::Socket;

my $port = shift or die "Usage: $0 <port>";

my $socket = new IO::Socket::INET(
        LocalHost => '0.0.0.0',
        LocalPort => $port,
        Proto => 'tcp',
        Listen => 1,
        Reuse => 1,
        )
  or die "Cannot create socket: $!\n";

while (1) {
  my $c = $socket->accept();
  shutdown($c, 2);
}

您需要保存脚本的 PID 或找到并终止它,因为它在保持给定端口打开的同时运行无限循环。

相关内容