簡體   English   中英

在 shell 中將“python -m SimpleSTTPServer”的結果傳遞給管道

[英]In shell pass results of "python -m SimpleSTTPServer" to pipe

我正在嘗試將 Python CLI“SimpleHTTPServer”命令的輸出發送到管道,以便 grep 結果。 但似乎輸出的第一行沒有被傳遞到管道,我無法弄清楚為什么。

這是運行命令的典型輸出。 第一行表明它已經啟動了一個服務器,以及它正在使用的端口。 然后它會在發生時報告各種網絡活動。 所以如果我運行python -m SimpleHTTPRequest然后加載 index.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並將其以“This is 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>&2stdout重定向到stderr ,這使得所有三行都顯示出來,而不像預期的那樣傳遞到管道。 根據this answer的討論,我嘗試從stdin重定向到stdout 0>$1 ,但這並沒有將任何行發送到管道。 我嘗試根據這個答案將 python 命令放在大括號中,但它沒有改變結果。 很明顯,網絡活動日志正在發送到stderr ,但尚不清楚第一行的去向。 我也在管道后嘗試使用grep ,結果相同。 在所有情況下,輸出的第一行都不會在管道之后到達stdin

看來 python "SimpleHTTPServer" 第一行輸出不會輸出到stdoutstderr ,所以我無法將它傳遞給管道。 怎么了?


如果有人有更好的方法來解決這個問題,這就是我想要做的。 我想要一個單行 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 服務器實現並發的方式有關,而它在調用處理客戶端請求的 cuntion serve_forever()之前沒有刷新stdout (參見Lib/http/server.py ) . 您可以通過在Lib/http/server.py 的第 1247 行print的調用中將, flush=True附加到函數參數中來自己測試。

由於我假設您無論如何都想使用 Python3 的 HTTP 服務器,因此您可以使用以下 bash 腳本來完成啟動 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.*:\K\d+')
echo "Server running on port ${port}"

# Opens the site
open "http://localhost:${port}"

請注意,之后您需要終止服務器進程。

希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM