APIKey 你的 API 密钥
。kill -9 $(cat server.pid)
。#!/bin/bash function server { read il echo "recv_il: $il" >&2 method=$( echo "$il" | cut -d" " -f1) path=$( echo "$il" | cut -d" " -f2) proto=$( echo "$il" | cut -d" " -f3) echo "method: $method" >&2 echo "path: $path" >&2 echo "proto: $proto" >&2 declare -A hdr while read line; do sline=`echo $line | tr -d '[\r\n]'` [ -z "$sline" ] && break echo "recv_hdr: $line" >&2 hdr_k=$(echo $line | cut -d":" -f1) hdr_v=$(echo $line | cut -d":" -f2- | cut -c2- | tr -d '[\r\n]') hdr[$hdr_k]="$hdr_v" done echo "recv_hdr_end" >&2 relpath=$(realpath "$(pwd)$path") if [[ "$relpath" != "$(pwd)"* ]]; then echo "possible path traversal attack: $relpath" >&2 echo "pwd: $(pwd)" >&2 echo "relpath: $relpath" >&2 echo -ne "HTTP/1.1 403 Forbidden\r\n" echo -ne "\r\n" echo -ne "possible path traversal attack: $relpath" exit 0 fi echo "relpath: $relpath" >&2 if [ $method = "GET" ]; then if [ ! -f "$relpath" ]; then echo -ne "HTTP/1.1 404 Not Found\r\n" echo -ne "\r\n" echo -ne "not found: $relpath" exit 0 fi echo -ne "HTTP/1.1 200\r\n" echo -ne "\r\n" cat "$relpath" exit 0 fi if [ $method != "POST" ]; then echo -ne "HTTP/1.1 405 Method Not Allowed\r\n" echo -ne "\r\n" exit 0 fi if [ "${hdr[Authorization]}" != "APIKey $KEY" ]; then echo -ne "HTTP/1.1 401 Unauthorized\r\n" echo -ne "\r\n" exit 0 fi body_file=$(mktemp) body_len=0 if [ ! -z "${hdr[Content-Length]}" ]; then echo "hdr_cl > body_len" >&2 body_len="${hdr[Content-Length]}" fi echo "body_len: $body_len" >&2 echo "body_file: $body_file" >&2 dd of=$body_file bs=1 count=$body_len mkdir -p $(dirname "$relpath") >&2 cp -v $body_file "$relpath" >&2 echo -ne "HTTP/1.1 201 Created\r\n" echo -ne "\r\n" echo -ne "created: $relpath\r\n" rm -rvf $body_file >&2 } if [ -z "$PORT" ]; then PORT=3000 fi if [ -z "$KEY" ]; then KEY=$(uuidgen) fi if [ "$EXEC" = "server" ]; then server exit 0 fi SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) PID=$$ PIDFILE="$SCRIPT_DIR/server.pid" if [[ -f "$PIDFILE" && -d "/proc/$(cat $PIDFILE)" ]]; then echo "one instance is running, refuse to start another" exit 1 fi if [ -f "server.sh" ]; then echo "DO NOT START SERVER WHEN CURRENT WORKING DIRECTORY IS SAME AS SCRIPT DIRECTORY" echo "THIS MAY CAUSE UNEXPECTED OVERWRITING SERVER AND RCE" echo "EXITING" exit 1 fi echo "PID=$PID" echo $PID > $PIDFILE echo "PIDFILE=$PIDFILE" echo "KEY=$KEY" while true; do nc -vlp $PORT -c "EXEC=server KEY=$KEY $0" done
1 trepwq 268 天前 via iPhone ![]() nc 换成 socat ,可以端口复用 |
![]() | 2 heimoshuiyu 268 天前 太酷辣 |
![]() | 3 sagaxu 268 天前 python -m http.server $PORT php -S localhost:$PORT jwebserver -p $PORT ruby -run -e httpd -p $PORT |
![]() | 4 baobao1270 OP @sagaxu 你这个要装编程环境啊,而且只能读不能写 |
![]() | 5 sagaxu 268 天前 @baobao1270 大部分 Linux 发行版依赖 Python ,不用另外安装。以前写 web 服务的时候,直接用 linux 自带的 inetd 监听端口,收到请求时调用 CGI 调用处理程序,CGI 可以是任何语言写的,只要这个语言能读 stdio 和环境变量以及写入 stdout 。像 Ubuntu 标准版自带的 busybox 也自带了一个 httpd ,可以提供 CGI 转发。 |
6 zsh2517 268 天前 ![]() @baobao1270 偏个题,如果考虑编程环境,并且需要上传的话,可以选择 https://pypi.org/project/uploadserver/ ,用法和 http.server 一样 python3 -m uploadserver ,不过不是标准库,需要 python 环境并且 pip 装包。 --- 我之前也想过,有文件、网路 IO 的情况下,shell 是不是也能作为 web 服务器,结果今天真看到有人实现出来了 |
8 w568w 267 天前 ![]() cool ,这才是真正的 shell 另有一些语法风格上的建议: 1. function 关键字是兼容一些远古 shell 给出的。既然指定了 bash ,用 server() {} 就好了; 2. 函数内的变量最好用 local 声明,否则作用域会泄漏到函数外; 3. 可以用 shellcheck 过一遍,可能有其他忽略的点 |
![]() | 9 dianso 267 天前 ![]() shell 做不到的。 你这个依赖 netcat 啊 和 python go 开个 https 有啥区别。 |
10 ruzztok 267 天前 nc ,可不是所有系统都自带哦。。 |
11 ai277014717 267 天前 可以再交给 GPT 润色一下 |