我的Makefile:
foo:
echo -n "d41d8cd98f00b204e9800998ecf8427e" | openssl dgst -md5 -hmac "1@123456"
当我运行:make foo
时,输出与直接在shell上运行相同命令的结果不同。(mac m2 arm64)
MacBook-Air:tmp $ make foo
echo -n "d41d8cd98f00b204e9800998ecf8427e" | openssl dgst -md5 -hmac "1@123456"
b6977416b3597483a9e416f4c04a1dcd
MacBook-Air:tmp$ echo -n "d41d8cd98f00b204e9800998ecf8427e" | openssl dgst -md5 -hmac "1@123456"
44ac6a36a27b1e5352a14e803929516f
但是当我在amd64 Ubuntu环境中执行相同的操作时,结果是一致的。
tmp$ make foo
echo -n "d41d8cd98f00b204e9800998ecf8427e" | openssl dgst -md5 -hmac "1@123456"
MD5(stdin)= 44ac6a36a27b1e5352a14e803929516f
echo -n "d41d8cd98f00b204e9800998ecf8427e" | openssl dgst -md5 -hmac "1@123456"
MD5(stdin)= 44ac6a36a27b1e5352a14e803929516f
我很感激你的指导。
1条答案
按热度按时间hvvq6cgz1#
echo
命令内置在shell中,因此它的行为取决于shell,这在不同平台之间是不同的。默认情况下,make
运行/bin/sh
,而不是环境中设置的$SHELL
。如果删除
openssl
命令,可以清楚地看到行为差异-macOS上的sh
echo不理解-n
作为一个选项,但只是将其包含在输出¹中。你可以像这样复制这个行为:(一个复杂的因素是,
make
试图聪明地了解何时需要shell,何时可以直接使用exec()
执行命令-所以没有管道的普通echo
可能会执行后者并最终运行/bin/echo
,即使在Mac上也能很好地理解-n
。但是命令的任何复杂性都将导致它由shell运行。)您可以在
Makefile
中设置SHELL
,但这会引入它自己的一组可移植性问题;例如,如果您将其设置为/bin/zsh
,则Makefile将不会在未安装zsh
的系统上运行,或者将其安装在/usr/bin
或/usr/local/bin
中。我会将
echo -n
更改为printf
;这样,它在shell之间是一致的,并且printf
已经没有追加换行符。事实上,忘记echo
的存在并始终使用printf
可能是一个好主意(当您需要换行符时,只需在末尾添加\n
)。但是如果你更愿意设置
SHELL
,我会这样做:这告诉
make
使用环境变量的任何设置,这通常是调用shell的内容。¹ macOS附带的Bash 3.2在作为
sh
调用时会更改其echo
行为。较新的版本已经停止这样做了,即使设置了POSIXLY_CORRECT,因为虽然POSIX标准规定echo
不应该识别-n
,但它也直接承认echo
是不可移植的,并表示应该避免它,除非在明确的情况下-即你想要回显的东西字面上,并添加一个换行符,并没有参数,看起来像选项或反斜杠转义。