2

I have the below script:

#!/bin/sh

#parameters definition
ROOT_PATH=/var/www/
msql_psw="cc"
mysql_login="bb"
mysql_db_name="aa"

echo START MYSQL DUMP

NOW=$(date +"%Y-%m-%d")
SQLFILE="log-$NOW.sql"
mysqldump --add-drop-table -u "$mysql_login" --password="$mysql_psw" "$mysql_db_name" > "$ROOT_PATH/$SQLFILE"

When it's run with sh -x, it gives command not found errors for empty lines, and even non-empty lines don't work correctly:

sh -x export_db.sh 
+ $'\r'
: command not found2: 
+ ROOT_PATH=$'/var/www/\r'
+ msql_psw=$'cc\r'
+ mysql_login=$'bb\r'
+ mysql_db_name=$'aa\r'
+ $'\r'
: command not found8: 
+ echo START MYSQL $'DUMP\r'
START MYSQL DUMP
+ $'\r'
: command not found10: 
++ date +%Y-%m-%d
+ NOW=$'2014-10-02\r'
+ SQLFILE=$'log-2014-10-02\r.sql\r'
+ mysqldump --add-drop-table -u $'bb\r' --password= $'aa\r'
: No such file or directory/www/
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
LEM01
  • 871
  • 3
  • 15
  • 23
  • 1
    The only thing that's particularly wrong here is your lack of quotes -- should be `-u "$mysql_login" --password="$mysql_psw"`, etc. Run your script with `sh -x your.script` and see what it says it's actually running -- this will show if it's _really_ not substituting your variables in the command. – Charles Duffy Sep 26 '14 at 21:55
  • 2
    Oh -- actually, `$ROOT_PATH=foo` is very wrong; needs to be `ROOT_PATH=foo`, without the leading `$`. – Charles Duffy Sep 26 '14 at 21:57
  • The $root_path is a typo, I didn't used a $ in my script. I'll try that and let you know. Thanks – LEM01 Sep 27 '14 at 21:49
  • 1
    By the way -- passing passwords on the command line isn't secure, because all applications' command lines are visible to other users. (Some programs will edit their argument lists in place to obscure passwords, but that doesn't help against attacks that try to capture before that point). – Charles Duffy Sep 28 '14 at 04:53
  • Thanks for the replies, but I'm still missing something.. Also every blank line is interpreted and returns a "Command not found message" .. Why would that be? – LEM01 Oct 02 '14 at 19:15
  • 3
    because they aren't blank. DOS-style newlines are `$'\r\n'`, UNIX newlines are just `$'\n'`, so when a UNIX system sees a line that would be blank on a DOS system, it reads the `$'\r'` as content. Your scripts need to be saved as UNIX text files, not DOS text files. – Charles Duffy Oct 02 '14 at 19:43
  • Gets them every time.... – David C. Rankin Oct 02 '14 at 20:13
  • Finally got it working! So thanks yo Charles Duffy, I figured out that the main issue was simply the file encoding that wasn't set to UNIX. For the rest of the code it worked fine just used curly brace for the variables. – LEM01 Oct 03 '14 at 10:29
  • Curly braces do not replace quotes. If your variables contain spaces, glob expressions, etc., curly braces will do nothing to help. I've removed the edit inaccurately claiming otherwise. – Charles Duffy Oct 03 '14 at 14:32
  • You can test this yourself: `var='foo bar'; printf '%s\n' $var; printf '%s\n' ${var}; printf '%s\n' "$var"` -- only the third one, with the quotes, keeps `foo` and `bar` together in one parameter; `$var` and `${var}` act precisely the same. – Charles Duffy Oct 03 '14 at 14:34
  • From: https://gist.github.com/mymaneesh/7583980 `Problem: $'\r': command not found` `Solution: create a ~/.bash_profile(in home directory) that contains` `export SHELLOPTS` `set -o igncr` – Jesse Chisholm Jun 02 '17 at 23:30
  • @JesseChisholm, that's a very partial solution -- it works for scripts run with `#!/bin/bash`, but not `#!/bin/sh` (where implemented by `ash`, `dash`, `ksh` or another non-bash shell). – Charles Duffy Apr 25 '18 at 00:49

1 Answers1

5

$'\r is the shells way of writing a CR character -- a carriage return. DOS-formatted text files end with CRLF -- in shell parlance, $'\r\n', whereas UNIX text files end with only $\n. Thus, when a DOS-formatted text file is read by UNIX, each line appears to have an extra $\r on the end.


Beyond that, some notes (in places, relevant only to prior versions of the question):

Expansion operators aren't used in assignments, so

$ROOT_PATH=/var/www/

needs to be

ROOT_PATH=/var/www

Beyond that -- use quotes on all expansions. That is:

mysqldump \
  --add-drop-table \
  -u "$mysql_login" \
  --password="$mysql_psw" \
  "$mysql_db_name" \
  >"$ROOT_PATH/$SQLFILE"

Otherwise, variables will be split by IFS, glob-expanded, etc.

Finally -- when making such a bold claim as that variables aren't being substituted, try proving it by using set -x in your script (or starting it with #!/bin/sh -x, or running it manually with sh -x yourscript) to log the commands the shell runs as they're actually invoked post-expansion.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441