使用 AWK 进行网络管理

作者:Juergen Kahrs

脚本语言 AWK 与网络有什么关系?在 1996 年 5 月的 LJ 中,Ian Gordon 向我们介绍了 AWK,并演示了如何使用这种属于 Linux 和每个 UNIX 兼容操作系统的脚本语言来解决常见问题。他总结道

如果您的主要关注点是以最快的速度编写一个可工作的程序,您可能不想花费一周的时间与 C 或 C++ 搏斗,以完善最高效的算法。通过牺牲 C(或其他编译语言)的速度优势和控制功能来换取易用性,gawk 让您可以快速且相对轻松地完成工作。

考虑到这种效率,如果能够使用简短的 AWK 脚本访问网络服务,那将是很好的。但是,标准 AWK 没有用于网络的函数,并且大多数 AWK 用户可能会反对引入此类函数。AWK 应该保持现在这样的小巧、简单且强大的语言。GNU AWK 的 3.1 版本没有引入用于套接字访问的特殊函数(如 Perl 和 C 那样),而是为此使用了一个特殊的文件名。通过将网络连接视为文件,即使是新手也可以用几行 AWK 代码编写 Web 客户端。
查找谁已登录

让我们看一个例子。它向您本地计算机的 finger 服务询问特定用户是否已登录。

BEGIN {
 NetService = "/inet/tcp/0/localhost/finger"
 print "
 while ((NetService |& getline) > 0)
   print $0
 close(NetService)
}

将此脚本存储在一个名为 finger.awk 的文件中,并通过键入 gawk -f finger.awk 让 GNU AWK 3.1 执行它。奇怪的管道符号 |& 是 AWK 语言中为网络添加的第二个也是最后一个补充。当通过网络通信时,我们必须使用 |& 而不是简单的 |

在告诉机器上的服务它正在查找哪个用户后,程序重复读取构成回复的行。当不再收到行(因为服务已关闭连接)时,程序在完成之前关闭套接字。尝试将 name 替换为您的登录名或已登录的其他人的姓名。如果您想要当前所有已登录用户的列表,请将 name 替换为空字符串 ("")。此外,将 localhost 更改为您本地网络中的另一台机器名称;这样做可以让您观察远程位置的机器上谁已登录。

可口可乐售货机

好吧,这并不是一个真正令人兴奋的应用程序。您获得的结果与您在 shell 提示符下键入 finger name@localhost 获得的结果相同。所以,让我们尝试一个真正有用的应用程序。如今,许多可口可乐售货机都连接到互联网。可以在 http://www5.biostr.washington.edu/~jsp/coke.html 找到此类机器的简短列表。在那里,您会看到访问它们的方式与我们在第一个(不太令人兴奋的)示例中所做的方式相同——finger 请求。让我们从列表中取出第一台可口可乐售货机,并询问该机器有哪些种类的软饮料可供选择。

BEGIN {
 NetService = "/inet/tcp/0/cs.wisc.edu/finger"
 print "coke" |& NetService
 while ((NetService |& getline) > 0)
   print $0
 close(NetService)
}

通常,您会收到包含当前可用的不同口味的可乐和沙士信息的回复。如果您在那里有一个帐户,您还可以订购饮料。许多其他类型的机器也连接到互联网。(请参阅资源。)

即使我们删除了最后的 close 命令,所示的两个示例也都可以工作,因为操作系统在脚本执行结束时默认关闭任何打开的连接。为了避免可移植性问题,我们总是显式关闭连接。

德国天气

与可口可乐售货机服务不同,我们访问的大多数 Web 服务通常使用名为 HTTP 的协议通过互联网传输 HTML 页面。对大多数人来说,这就是 真正的 互联网。我们可以使用 GNU AWK 访问 真正的 互联网吗?当然可以。我们只需要确保连接到 Web 服务器的端口 80 而不是 finger 端口。这样,我们可以连接到 Yahoo 机器,让它告诉我们我们居住地的天气状况。

BEGIN {
 NetService = "/inet/tcp/0/
 print "GET http://weather.yahoo.com/forecast/Bremen_DL_c.html" |&
   NetService
 while ((NetService |& getline) > 0)
   print $0
 close(NetService)
}

在启动此脚本之前,请确保您知道您的提供商使用的代理服务器,并将代理服务器的名称插入第二行。如果您不使用代理,请插入 Web 服务器的名称 (weather.yahoo.com)。结果是网页的 HTML 内容。这取决于您的脚本将其转换为更易读的形式,或提取感兴趣的详细信息以供进一步处理。

阅读股票行情

有时我们并不真正对查看网页感兴趣。想象一下一个 Web 机器人(或代理),它每 15 分钟查看一次摩托罗拉股票的报价,并在价格达到某个限额时向您发送电子邮件。每 15 分钟执行一次的命令行调用很容易编写并存储在 shell 脚本中。此外,根据数据文件的内容,发送电子邮件与编写 shell 脚本一样简单。这是一个为您读取股票行情的脚本

BEGIN {
 NetService = "/inet/tcp/0/
 print "GET http://quote.yahoo.com/q?s=MOT&d=v1" |&
   NetService
 while ((NetService |& getline) > 0)
   print $0
 close(NetService)
}

同样,您必须将您的代理服务器名称插入第二行。在脚本执行期间,请求将发送到 Yahoo 的报价服务器,生成的网页应由您重定向到一个文件。使用 grep 命令,可以从 HTML 文本中提取价格并与限额进行比较。

高级应用

在这些示例中,我们已经看到如何基于相同的简单框架编写有用的应用程序。此框架仅代表可以使用 GNU AWK 的网络设备完成的一小部分工作。TCP 和 UDP 连接都可用,并且可以编写客户端和服务器。更多高级应用程序可以在补充 GNU AWK 源代码分发的官方文档的小型手册中看到。(请参阅资源。)

像文件一样处理网络连接并不是 GNU AWK 独有的功能。当 TCP/IP 在 80 年代早期集成到 BSD UNIX 中时,套接字 API 的创建者最初打算让网络连接即使对用户来说也像特殊文件一样出现。但是,事实证明,网络有很多特殊情况,无法通过统一的文件处理方式来处理。后来,门户文件系统 方法被集成到 BSD UNIX 中。门户类似于 GNU AWK 的特殊文件,但作为文件系统集成到操作系统中。这效果很好,因为用户甚至可以在 shell 提示符下建立连接。最新版本的 Korn shell (ksh93) 在 shell 级别提供了几乎相同的概念 (/dev/tcp)。这些方法都没有在用户中获得广泛接受。即使 Richard Stevens 关于门户的文章(请参阅资源)也没有改变这一点。

在过去一年中,在 shell 级别获得一定程度接受的另一种网络方法是工具 netcat。最初是一种 UNIX 黑客工具,它只是将进程的标准输入和输出绑定到网络连接。它既了解 TCP 又了解 UDP,可以充当服务器,并允许“端口扫描”,即检查是否有服务器在特定端口上监听。这个工具简单易用且功能强大,但源代码中的一些评论非常不专业。我很少在源文件中看到如此大量的粗俗咒骂、愚蠢的炒作和纯粹的无知。最近,netcat 已移植到 Windows NT。对于 NT 的谦卑用户来说,这样的工具就像期待已久的启示。

Microsoft Windows

回到纯粹的 AWKism 和这种信仰的不同形式。除了 Linux 之外,GNU AWK 3.1 的网络功能在哪些平台上可用?它应该在所有符合 XPG4 规则的 UNIX 系统上工作;这包括每个具有重要市场份额的 UNIX。尽管 GNU AWK 3.1 的确切发布日期尚未确定,但作为 Cygwin 工具集的一部分,这个新功能也应该在 Microsoft Windows 95 和 NT 上可用,只要两者都发布。Cygwin 是一个 UNIX 兼容的编程环境,它运行在 Microsoft 的 Win32 API 之上。它目前仅作为 Beta 版本提供,但已经能够编译自己的源代码集。

在撰写本文时,GNU AWK 3.0.3 的编译工作正常,但 3.1 引起了问题。如果您打算在此环境中编译源代码,请准备好遇到一些麻烦。最重要的是,避免在您用于使用 GNU AWK 进行网络的同一台机器上进行编译。如果您只有一台机器可用,请在编译和测试之间重新启动。截至 Cygwin 工具集 B20 版本,用 GNU AWK 编写的客户端和服务器在 Windows 95 上工作,但在 NT 4.0 SP3 上没有服务器工作。截至 B20.2 版本,编译器支持将文件 gawk.exe 与所有需要的动态库静态链接。这将允许将 GNU AWK 解释器作为一个单独的可执行文件分发,但此可执行文件无法工作。这些问题应该在您阅读本文时得到解决;因此,Windows 95 上的网络应该可以工作。

权衡

我们已经看到,通过特殊设备进行网络访问对于许多有用的应用程序来说已经足够好了,但是我们必须为此方便的访问方法权衡一些高级功能。有些事情在 AWK 采用的易于使用的框架内根本不可能实现,即

  • 广播

  • 非阻塞读取

  • 超时

  • 派生服务器进程

尽管缺少这些高级功能,但已经在 GNU AWK 中实现了诸如原型“Web 服务器”或“移动代理”之类的高级应用程序。如果您需要并可以处理广播或非阻塞读取等功能,则应使用 Perl 或 C 而不是 AWK。

资源

Juergen Kahrs (juergen.kahrs@t-online.de) 曾在 MS-DOS 上使用 AWK 进行时间序列分析、统计分析和图形演示,主要用于神经学数据。1996 年,他转用 Linux,并很高兴看到他的旧脚本仍然在更高效的编程环境中运行。他已经接受了 AWK 永远不会成为主流的事实,并乐于看到 C 程序员花费夜晚追逐 NULL 指针访问。Juergen 为将 TCP/IP 支持集成到 gawk 中做了初步工作。

加载 Disqus 评论