工作中的一个需求需要为一个现存的功能提供Web访问界面由于这个功能是用Shell编写的首先想到的解决方案是通过在Shell中开启一个Server Socket来实现一个简单的HTTP服务器提供给浏览器访问我并不需要实现所有的HTTP协议只要能够处理特定的GET请求即可这个简单的HTTP服务器将会从浏览器发送的GET请求中截取指定参数然后通过系统调用执行现存的Shell脚本在网上查找了一下Shell Socket的相关信息发现实现技术还挺多摘录了两种方法(为简明起见所列代码做了简化)记录于此以备忘 Perl use strict; use IO::Socket;
my $server_socket = IO::Socket::INET>new ( LocalPort => Listen => SOMAXCONN Proto => tcp Reuse => Timeout => ) or die SERVER SOCKET ERROR!n;
while() { next unless my $connection = $server_socket>accept; my $url = get_url($connection);
if ($url =~ /^*\/(\?param=(*))?$/) { if ($) { system((myshell $)); #myshell是现有功能的shell程序 } send_page($connection); } else { send_($connection); } $connection>close; }
sub send_ { my $sock = shift; print $sock HTTP/ NOT FOUND\r\n\r\nNOT FOUND\r\n; }
sub send_page { my $sock = shift; my $html = HTTP/ OK\r\nContentType: text/html; charset=UTF\r\n\r\n <html><head><meta httpequiv=ContentType content=text/html; charset=UTF/> <title></title></head><body><form method=get><input type=text name=param/> <input type=submit value=Submit/></form></body></html>\r\n;
print $sock $html; }
sub get_url { my $sock = shift; my $line = ; while(($line = <$sock>) ne \r\n) { if ($line =~ /GET ([^ ]+) /) { return $; } } return ; } 保存脚本为appserverpl 以perl appserverpl &启动然后用浏览器访问:///<ip>:/即可由于Linux发行版上一般都自带Perl这个方法的适用性还是比较普遍不过需要熟悉一点Perl语法 nc命令 while(/bin/true) do nc l p c $(cat /path/to/myshell) #myshell从标准输入读取http请求将http响应打印到标准输出 done 这种方式可以完全通过shell来实现相对简洁但要求nc支持c选项且myshell必须是sh语法(不能使用bash)如果把shell脚本换成二进制程序可以使用e选项不过有些Linux发行版上默认的nc不支持c和e选项(在ubuntu desktop和RHEL上就不行但在ubuntu server上可以) 由于部署环境是RHEL最终我使用了第一种方式来实现我的需求但第二种方法也很有吸引力通过在Shell中使用Server Socket可以轻易地将一个普通脚本或程序包装成一个网络服务这在某些情况下非常有用比如来自产品人员或决策者的临时的访问某些功能或数据的需求 |