Aar*_*sau 5 shell make variable
我有一个 make 脚本来执行 3 个任务:
对于这些任务,脚本需要 3 个输入:
出于某种原因,每当我read输入时,它都会保存到正确的变量中,但内容是我保存它的变量名,没有第一个字母。我似乎无法找出它为什么会这样做。
这是Makefile:
SHELL := /bin/bash
default:
@echo "Welcome!";\
echo -n "Please enter the MySQL host (default: localhost):";\
read host;\
host=${host:-localhost};\
echo -n "Please enter the MySQL username:";\
read username;\
echo -n "Please enter the MySQL password:";\
read -s password;\
mv includes/config.php.example includes/config.php 2>/dev/null;true;\
sed 's/"USER", ""/"USER", "$(username)"/g' includes/config.php > includes/config.php;\
sed 's/"PASSWORD", ""/"PASSWORD", "$(password)"/g' includes/config.php > includes/conf$
echo $username;\
echo $password;\
mysql -u "$username" -p"$password" codeday-team < ./codeday-team.sql;\
echo "Configuration complete. For further configuration options, check the config file$
exit 0;
Run Code Online (Sandbox Code Playgroud)
输出是:
Welcome!
Please enter the MySQL host (default: localhost):
Please enter the MySQL username:<snip>
Please enter the MySQL password:sername
assword
ERROR 1045 (28000): Access denied for user 'sername'@'localhost' (using password: YES)
Configuration complete. For further configuration options, check the config file includes/config.php
Run Code Online (Sandbox Code Playgroud)
如您所见,它输出sername和assword。对于我的生活,我无法解决这个问题!
虽然这篇文章的目的是解决read错误,但我希望得到任何建议、错误报告或建议。我可以赏金给他们。
感谢您的帮助!
你make在那里混合了 shell 和变量。无论make和外壳使用$他们的变量。
在 Makefile 中,变量是$(var)或$v用于单字母变量,和/$var或${var}在外壳中。
但是如果你写$var在一个 Makefile 中,make就会把它理解为$(v)ar. 如果要将文字传递$给 shell,则需要将其输入为$$, as in $$varor$${var}以便它成为$var或${var}for shell。
另外,make运行sh,不能bash解释的代码(编辑,遗憾错过了你的SHELL := /bin/bash上面,请注意,许多系统没有bash在/bin他们是否有bash在所有和:=是GNU特定的),所以你需要使用sh的语法出现。echo -n,read -s是zsh/bash语法,不是sh语法。
最好在这里添加一个zsh/bash脚本来做到这一点(并在 上添加构建依赖项bash)。就像是:
#! /usr/bin/env bash
printf 'Welcome\nPlease enter the MySQL host (default: localhost): '
read host || exit
host=${host:-localhost}
printf "Please enter the MySQL username: "
read username || exit
printf "Please enter the MySQL password:"
IFS= read -rs password || exit
printf '\n'
mv includes/config.php.example includes/config.php 2>/dev/null
repl=${password//\\/\\\\}
repl=${repl//&/\\&}
repl=${repl//:/\\:}
{ rm includes/config.php &&
sed 's/"USER", ""/"USER", "'"$username"'"/g
s:"PASSWORD", "":"PASSWORD", "'"$repl"'"/g' > includes/config.php
} < includes/config.php || exit
mysql -u "$username" -p"$password" codeday-team < ./codeday-team.sql || exit
echo "Configuration complete. For further configuration options, check the config file"
Run Code Online (Sandbox Code Playgroud)
它解决了更多问题:
-r如果您想允许用户在其密码中使用反斜杠,则在读取密码时需要。IFS=,如果你想允许用户有一个密码,在空格开始或结束;true后mv不会做你认为它会做的事情。它不会取消errexit选项的效果(对于make使用 调用 shell 的实现-e)。你需要||true代替。在这里,我们不是在使用,errexit而是|| exit在需要的地方自行处理错误。&和s:pattern:repl:分隔符(此处:),否则它将不起作用(并且可能会产生令人讨厌的副作用)。你不能做sed ... < file > file,因为file在sed开始之前会被截断。一些sed实现支持一个-ior-i ''选项。或者,您可以使用perl -pi. 在这里,我们所做的相当于perl -pi手动(在输入文件打开读取后删除并重新创建它),但没有处理文件的元数据。
在这里,最好使用示例之一作为输入,最后一个作为输出。
它仍然没有解决更多问题:
config.php创建的权限来自当前umask可能是世界可读的并且由运行的用户拥有make。umask如果includes目录不受其他限制,因为该文件包含敏感信息,则您可能需要调整和/或更改所有权。"字符,则可能会中断(这次是php)。您可能想要禁止那些(通过返回错误)或以该php文件的正确语法为它们添加另一层转义。您可能会遇到与反斜杠类似的问题,并且您可能还想排除非 ascii 或控制字符。在命令行上传递密码mysql通常是一个坏主意,因为这意味着它会显示在ps -f. 最好使用:
mysql --defaults-file=<(
printf '[client]\nuser=%s\npassword="%s"\n' "$username" "$password") ...
Run Code Online (Sandbox Code Playgroud)
printf是内置的,它不会出现在ps输出中。
$host未使用该变量。
您没有使用 Makefile 的任何功能,您是否尝试在单个 shell 中编写这些行?
接下来在您使用的 Makefile 中
echo $username;\
echo $password;\
Run Code Online (Sandbox Code Playgroud)
make 将解析$username为$u(空变量) + sername(字符串)
尝试更换$username的$$username,如果你想留在Makefile文件。