긴 html 문자열을 bash 스크립트에 인수로 전달합니다(파일 이름이 너무 깁니다).

긴 html 문자열을 bash 스크립트에 인수로 전달합니다(파일 이름이 너무 깁니다).

bash 스크립트에 대한 입력으로 html 문자열을 전달합니다.

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.

내 bash 스크립트에 매개변수로 완전한 HTML 문자열을 제공하고 싶습니다. 저는 bash 스크립팅을 처음 사용하므로 이 문제를 해결하는 더 좋은 방법이 있을 수 있지만 잘 모르겠습니다. 내 한 가지 제한 사항은 실제로 Python에서 bash 스크립트를 호출해야 한다는 것입니다. bash 스크립트에 긴 HTML 문자열을 매개변수로 전달하는 방법은 무엇입니까?

답변1

TL, DR: bash를 사용하지 마세요. 필요하지 않습니다.

두 가지 질문이 있습니다. 가장 큰 것은 논쟁에 대한 언급입니다. 또 다른 가능성은 명령줄 길이 제한입니다.

주요 문제

TL, 박사:

  1. 필요하지 않을 때는 셸을 호출하지 마세요.
  2. 보다 일반적으로는 무언가를 여러 번 구문 분석해야 하는 상황에 빠지지 않도록 하세요. 제대로 하기가 어려운 경우가 많습니다.

다음과 같은 bash 명령을 실행 중입니다.

./email.sh '[email protected]' 'Something happened' '<html>
<body>
You are heading for trouble.
</body>
</html>'

Bash는 명령을 구문 분석하고 ./email.sh세 가지 인수를 사용하여 프로그램을 실행합니다. 프로그램은 ./email.sh우연히 다른 bash 인스턴스를 실행하고 있지만 이는 단지 우연의 일치일 뿐입니다. 두 가지 목적 모두에 동일한 쉘을 사용할 필요는 없습니다.

하지만 작은따옴표를 포함하도록 HTML의 텍스트를 변경하면 어떻게 될까요?

./email.sh '[email protected]' 'Something happened' '<html>
<body>
You're heading for trouble.
</body>
</html>'

에 전달된 세 번째 매개변수는 이제 로 ./email.sh끝납니다 Youre. 네 번째 인수 heading, 다섯 번째 인수 for, 여섯 번째 인수 가 있으며 trouble.일단 ./email.sh반환되면 bash는 명령을 구문 분석하고 실행하려고 시도하여 </body>오류가 발생합니다.

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

약간 다른 HTML을 사용하면 다양한 오류가 발생할 수 있습니다. 컴퓨터에서 임의의 명령이 실행될 수 있으며, 이메일에 무언가를 주입할 수 있는 악의적인 행위자가 지정한 명령일 수도 있습니다. 귀하의 코드는 거대한 보안 허점입니다!

xkcd327

짧은 해결책

중간에 큰 타격을 가해도 소용이 없습니다. 그것은 전혀 도움이 되지 않으며 큰 오류를 추가합니다.

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를 사용할 필요가 없습니다. 파이썬에서는 이 모든 것을 할 수 있습니다.

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'))

관련 정보