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 $$var
or$${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
实现支持一个-i
or-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文件。