I have a make script to perform 3 tasks:
- Import a MySQL database
- Move a configuration file
- Configure the configuration file
For these tasks, the script requires 3 inputs:
- MySQL Host
- MySQL Username
- MySQL Password
For some reason, whenever I read
an input, it saves to the right variable, but the content is the variable name that I save it to without the first letter. I can't seem to find out why it does that.
Here's the 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;
The output is:
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
As you can see, it outputs sername
and assword
. For the life of me I can't fix this!
While the purpose of this post is to solve the read
bug, I would appreciate any advice, bugs reports, or suggestions. I may award a bounty for them.
Thank you for helping!
Best Answer
You're mixing shell and
make
variables in there. Bothmake
and the shell use$
for their variables.In Makefile, variables are
$(var)
or$v
for single-letter variables, and$var
or${var}
in shells.But if you write
$var
in a Makefile,make
will understand it as$(v)ar
. If you want to pass a literal$
to the shell, you need to enter it as$$
, as in$$var
or$${var}
so that it becomes$var
or${var}
for the shell.Also,
make
runssh
, notbash
to interpret that code (Edit, sorry missed yourSHELL := /bin/bash
above, note that many systems don't havebash
in/bin
if they havebash
at all and:=
is GNU specific), so you need to usesh
syntax there.echo -n
,read -s
arezsh
/bash
syntax, notsh
syntax.Best here would be to add a
zsh
/bash
script to do that (and add a build dependency onbash
). Something like:It addresses a few more issues:
-r
when reading the password if you want to allow the user to use backslashes in their password.IFS=
if you want to allow the user to have a password that starts or ends in blanks;true
aftermv
doesn't do what you think it does. It doesn't cancel the effect of theerrexit
option (formake
implementations that call the shell with-e
). You'd need||true
instead. Here, we're not usingerrexit
but doing the error handling ourselves with|| exit
where needed.&
and thes:pattern:repl:
separator (here:
) or it won't work (and could have nasty side effects).You can't do
sed ... < file > file
, asfile
would be truncated beforesed
is even started. Somesed
implementations support a-i
or-i ''
option for that. Alternatively you could useperl -pi
. Here we're doing the equivalent ofperl -pi
manually (delete and recreate the input file after it has been open for reading) but without taking care of the file's metadata.Here, it would be better to use the example one as input and the final one as output.
It still doesn't address a few more issues:
config.php
is created with permissions derived from the currentumask
which is likely to be world readable and owned by the user runningmake
. You may need to adapt theumask
and/or change ownership if theincludes
dir is not otherwise restricted as that file contains sensitive information."
characters, that will likely break (this time forphp
). You'd want to either forbid those (by returning an error) or add another layer of escaping for them in the right syntax for thatphp
file. You're likely to have similar problems with backslash and you may want to exclude non-ascii or control characters as well.Passing the password on the command-line of
mysql
is generally a bad idea as that means it shows in the output ofps -f
. It would be better to use:printf
being built-in, it wouldn't show up inps
output.the
$host
variable is not used.