目 录CONTENT

文章目录

go 小程序

xlong
2024-06-14 / 0 评论 / 0 点赞 / 10 阅读 / 3378 字 / 正在检测是否收录...

指定监听一个端口,配置用户密码验证,访问接口执行shell脚本。

shell脚本需要写对路径,并且配置执行权限。

源码:

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
)

func main() {
	// 定义程序参数
	portPtr := flag.String("port", "8080", "Port to run the server on")
	shellScriptPtr := flag.String("shellScript", "your-shell-script.sh", "Path to the shell script to execute")
	logFilePtr := flag.String("logFile", "server.log", "Path to the log file")
	authUsernamePtr := flag.String("authUsername", "admin", "Username for authentication")
	authPasswordPtr := flag.String("authPassword", "password", "Password for authentication")
	flag.Parse()

	// 创建日志文件
	f, err := os.OpenFile(*logFilePtr, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Fatalf("Failed to open log file: %v", err)
	}
	defer f.Close()

	// 设置日志输出
	log.SetOutput(f)
	log.SetFlags(log.LstdFlags | log.Lshortfile)

	// 创建 HTTP 服务器
	http.HandleFunc("/execute", basicAuth(*authUsernamePtr, *authPasswordPtr, executeShellScript(*shellScriptPtr)))
	log.Printf("Starting server on port %s", *portPtr)
	log.Fatal(http.ListenAndServe(":"+*portPtr, nil))
}

func basicAuth(username, password string, next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		user, pass, ok := r.BasicAuth()
		if !ok || user != username || pass != password {
			w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
			w.WriteHeader(http.StatusUnauthorized)
			fmt.Fprintln(w, "Unauthorized")
			return
		}
		next(w, r)
	}
}

func executeShellScript(shellScript string) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			w.WriteHeader(http.StatusMethodNotAllowed)
			log.Printf("Method not allowed: %s", r.Method)
			respondWithJSON(w, http.StatusMethodNotAllowed, map[string]interface{}{
				"success": false,
				"message": "Method not allowed",
			})
			return
		}

		// 执行 Shell 脚本
		output, err := exec.Command("/bin/sh", "-c", shellScript).Output()
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			log.Printf("Error executing shell script '%s': %v", shellScript, err)
			respondWithJSON(w, http.StatusInternalServerError, map[string]interface{}{
				"success": false,
				"message": "Error executing shell script",
			})
			return
		}

		// 打印 Shell 脚本输出到日志
		log.Printf("Shell script '%s' output:\n%s", shellScript, output)

		// 返回 JSON 格式的响应
		w.WriteHeader(http.StatusOK)
		respondWithJSON(w, http.StatusOK, map[string]interface{}{
			"success": true,
			"message": "Shell script executed successfully",
		})
	}
}

func respondWithJSON(w http.ResponseWriter, statusCode int, payload interface{}) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(statusCode)
	json.NewEncoder(w).Encode(payload)
}

二进制命令执行:

监听5000端口,用户名:test,密码:123321 ,日志文件 my-log.txt ,执行shell脚本,当前目录/app/addApp.sh。

cat /data/fdroid/go/runserver.sh
#!/bin/bash

/app/shell-execute -port=5000 -shellScript=/app/addApp.sh -logFile=my-log.txt -authUsername=test -authPassword=123321

0

评论区