我正在尝试将Python CLI"SimpleHTTPServer"命令的输出发送到管道,以便grep结果。 但是似乎输出的第一行没有传递给管道,我不知道为什么。
下面是运行命令的典型输出。 第一行表示它已启动服务器及其正在使用的端口。 然后,它会在发生各种网络活动时报告它们。 因此,如果我运行python -m SimpleHTTPRequest
然后加载索引.html页面两次,则输出如下所示:
$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
127.0.0.1 - - [07/May/2018 21:08:31] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [07/May/2018 21:08:36] "GET / HTTP/1.1" 200 -
如果我将stderr
重定向到stdout
,然后发送到管道,我希望所有行都会在管道之后到达stdin
。 但这似乎并没有发生。 当我在管道后使用sed
并让它在所有行前面加上"这是 stdin:"时,输出的第一行不会出现。
$ python -m SimpleHTTPServer 2>&1 | sed "s/.*/This is stdin:&/"
This is stdin:127.0.0.1 - - [07/May/2018 23:35:07] "GET / HTTP/1.1" 200 -
This is stdin:127.0.0.1 - - [07/May/2018 23:35:11] "GET / HTTP/1.1" 200 -
我尝试了不同的重定向选项。 我可以使用1>&2
将stdout
重定向到stderr
,这使得所有三行都显示而无需按预期传递到管道。 根据此答案的讨论,我尝试使用0>$1
从stdin
重定向到stdout
,但这并没有将任何行发送到管道。 根据这个答案,我尝试将 python 命令放在大括号中,但它并没有改变结果。 很明显,网络活动日志正在发送到stderr
,但不清楚第一行的去向。 我也尝试在管道后使用grep
,结果相同。 在所有情况下,输出的第一行都不会到达管道之后的stdin
。
看来python"SimpleHTTPServer"的第一行输出既不会stdout
也不会stderr
,所以我不能把它传递给管道。 发生了什么事情?
如果有人有更好的解决方法,这就是我正在尝试做的事情。 我想要一个单行 shell 命令,它将 (1( 使用 python SimpleHTTPServer 启动本地服务器;(2(找出它使用的端口号;然后 (3( 在该本地服务器端口打开浏览器。 我知道 SimpleHTTPServer 的默认端口是 8000;但是如果那个已经在使用中,它会分配一个不同的,所以我需要知道这一点。 我也知道我可以告诉SimpleHTTPServer使用哪个端口,但如果该端口已经在使用中,那么命令将失败。 我知道在python中你可以问正在使用什么端口,但我需要一个shell脚本从不同的应用程序运行。 因此,我决定在命令启动服务器时侦听命令的输出,重新识别 4 位端口号,使其成为变量,然后使用该变量在浏览器中打开正确的端口。 我希望以下内容有效,但事实并非如此。
$ port=$(python -m SimpleHTTPServer 2>&1 | grep -o '[0-9]{4}') ; open http://localhost:$port
我指的是Python3和模块http.server
,因为Python2已经到了它的生命周期的尽头。但是,那里也发生了同样的情况。您观察到的行为与以下方式有关:此HTTP服务器正在实现并发性,而在调用处理客户端请求的cuntionserve_forever()
之前,它没有刷新stdout
(请参阅Lib/http/server.py(。您可以通过在 Lib/http/server.py 第 1247 行的print
调用中将, flush=True
附加到函数参数中来自己测试这一点。
由于我假设无论如何您都想使用 Python 3 的 HTTP 服务器,因此您可以使用以下 bash-script 来完成启动 HTTP 服务器的任务,找到它的侦听端口并打开系统的默认浏览器以打开它:
#!/bin/bash
# Runs your server process
(python3 -m http.server &) >/dev/null 2>&1
# Adds delay, so that server started up
sleep 0.5
# Retrieves PID of the running server process
pid=$(pgrep -f "python3 -m http.server")
# Uses lsof to find the listening sockets
# -a is used to 'and' two filters
port=$(lsof -a -i -p $pid | grep -oP 'TCP.*:Kd+')
echo "Server running on port ${port}"
# Opens the site
open "http://localhost:${port}"
请注意,之后您需要终止服务器进程。
希望,这有帮助!