在标准输入上使用脚本调用 sh 并传递命令行参数

在标准输入上使用脚本调用 sh 并传递命令行参数

这当然有效。我可以运行./test1.sh cats并且参数cats被正确传递给ls.

$ cat test1.sh
#!/bin/sh
ls -l $1

您能否告诉我如何使第二个示例(内容与第一个示例相同,但已加密)以相同的方式工作?密码是“密码”。 openssl输出上面的脚本并ls -l运行,但是如何将命令行参数传递给它?

$ cat test2.sh
#!/bin/sh
echo "U2FsdGVkX1/m01Eg0CvZ7DiBi5Nf81+JrCWfKIDI9WtbkTZIVLhZskkKIioVfbSe"|openssl enc -base64 -d -aes-256-cbc|sh $1

澄清一下,test2.sh相当于

$ cat test3.sh
#!/bin/sh
printf '%s\n' '#!/bin/sh' 'ls -l $1' | sh $1

答案1

您在问题的早期版本中已经有了它 - 将-s选项传递给sh

echo "U2FsdGVkX1/m01Eg0CvZ7DiBi5Nf81+JrCWfKIDI9WtbkTZIVLhZskkKIioVfbSe" | openssl enc -base64 -d -aes-256-cbc | sh -s "$1"

这告诉 shell 从标准输入读取命令,同时接受其命令行上的参数(在 后面-s)作为来自标准输入的脚本代码的位置参数。当然,shell 变量应该始终被引用,除非您有充分的理由不这样做,并且从长远来看,将"@"(所有参数)传递给 shell 可能更有用。

test1.sh因此,在;中引用所有对 shell 变量的引用也是明智的。例如,

ls -l "$1"

第一个解决方案(上面介绍的)似乎适用于“正常”参数。但是,要处理以以下开头的参数的情况-,最好做sh -s -- "$1"(或 "$@")。例如,

#!/bin/sh
code="U2FsdGVkX1/m01Eg0CvZ7DiBi5Nf81+JrCWfKIDI9WtbkTZIVLhZskkKIioVfbSe"
echo "$code" | openssl enc -base64 -d -aes-256-cbc | sh -s -- "$@"

(我将加密的脚本放入变量中只是为了使命令行更短,因此它适合超级用户显示列)。

答案2

该脚本将要求输入密码,解密加密的脚本并使用传递给主脚本的第一个命令行选项运行它:

#!/bin/bash

bash <(
    openssl enc -base64 -d -aes-256-cbc <<<'U2FsdGVkX1/m01Eg0CvZ7DiBi5Nf81+JrCWfKIDI9WtbkTZIVLhZskkKIioVfbSe'
) "$1"

这不使用#!解密脚本的 - 行,但假设它可以正常运行bash(并且它总是解密成功)。解密脚本被传递到bash解密脚本通过openssl调用时的进程替换以及第一个命令行参数

要将解密的脚本写入磁盘,仅在正确解密(使用其预期的解释器)时运行它,然后将其删除:

#!/bin/bash

tmpscript=$(mktemp)
trap 'rm -f "$tmpscript"' EXIT

if ! openssl enc -base64 -d -aes-256-cbc <<<'U2FsdGVkX1/m01Eg0CvZ7DiBi5Nf81+JrCWfKIDI9WtbkTZIVLhZskkKIioVfbSe' >$tmpscript
then
    exit 1
fi

chmod +x "$tmpscript"
"$tmpscript" "$1"

如果您想将主脚本的所有命令行参数传递给解密的脚本,您应该将"$1"上面的示例更改为"$@".双引号很重要,因为它们确保传递各个参数时不会因空格而分割,也不会进行文件名通配。

相关内容