Bash

將長 html 字元串作為參數傳遞給 bash 腳本(文件名太長)

  • February 25, 2022

我將一個 html 字元串作為輸入傳遞給 bash 腳本:

Script.py


def bash(commandStr):
   subprocess.Popen(commandStr, shell=True, executable="/bin/bash")
 
def sendmail(subject, to, body):
   bash(f"./email.sh '{to}' '{subject}' '{body}'")

email.sh

#!/bin/bash

# args: 1 - TO address
#       2 - subject
#       3 - body

(
echo "To: $1";
echo "Subject: $2";
echo "Content-Type: text/html";
echo "MIME-Version: 1.0";
echo "";
echo "$3";
) | sendmail -t

這成功地只發送了 html 的一個子集,然後我得到了錯誤:File name too long

我想提供一個完整的 HTML 字元串作為我的 bash 腳本的參數。我是 bash 腳本的新手,所以可能有一種我不知道的更好的方法來解決這個問題。我的一個限制是我確實需要從 python 呼叫 bash 腳本。如何將長 HTML 字元串作為參數傳遞給 bash 腳本?

TL,DR:不要使用 bash,你不需要它。

有兩個問題。你最大的一個是引用的論點。另一個可能是命令行長度限制。

主要問題

長話短說:

  1. 當您不需要 shell 時,不要呼叫 shell。
  2. 更一般地說,避免陷入需要多次解析的情況。通常很難做到正確。

您正在執行 bash 命令,例如

./email.sh 'bob@example.com' 'Something happened' '<html>
<body>
You are heading for trouble.
</body>
</html>'

./email.shBash 解析這個命令並使用三個參數執行程序。該程序./email.sh碰巧執行了另一個 bash 實例,但這只是巧合:您不必為這兩個目的使用相同的 shell。

但是,如果您將 HTML 中的文本更改為包含單引號會怎樣?

./email.sh 'bob@example.com' 'Something happened' '<html>
<body>
You're heading for trouble.
</body>
</html>'

現在傳遞給的第三個參數./email.shYoure. 有第四個參數heading,第五個參數for和第六個參數trouble.然後,一旦./email.sh返回,bash 解析並嘗試執行命令</body>,導致錯誤

bash: -c: line 4: syntax error near unexpected token `newline'
bash: -c: line 4: `</body>'

使用一些稍微不同的 HTML,您可能會遇到各種不同的錯誤。你最終可能會在你的機器上執行任意命令,也許是惡意的人指定的命令,他們可以向電子郵件中註入一些內容。您的程式碼是一個巨大的安全漏洞!

第327章

一個簡短的解決方案

那個中間 bash 是沒用的。它根本沒有幫助你,並增加了一個巨大的錯誤。

def sendmail(subject, to, body):
   subprocess.Popen(["./email.sh", to, subject, body])

這更簡單,並且確實有效。

更強大的解決方案

如果電子郵件正文太長,您可能會遇到命令行長度(命令名、參數、環境變數)的限制。限制是 顯示的字節數getconf ARG_MAX

為避免這種情況,您可以將電子郵件正文作為輸入而不是作為命令行參數傳遞。

def sendmail(subject, to, body):
   subprocess.Popen(["./email.sh", to, subject], input=body.encode('utf-8'))

utf-8(如果需要,用正確的字元集替換。)

#!/bin/bash

# args: 1 - TO address
#       2 - subject
# stdin: body

(
echo "To: $1";
echo "Subject: $2";
echo "Content-Type: text/html";
echo "MIME-Version: 1.0";
echo "";
cat
) | sendmail -t

為什麼要使用 bash?

如果該電子郵件發送腳本正是您所展示的,那麼使用 bash 是沒有意義的。你可以在 Python 中完成這一切。

def sendmail(subject, to, body):
   mail = f"""\
To: f{to}
Subject: f{subject}
Content-Type: text/html
MIME-Version: 1.0

f{body}"""
   subprocess.Popen(["sendmail", "-t"], input=mail.encode('utf-8'))

引用自:https://unix.stackexchange.com/questions/692144