0

Please see below outputs, it looks like the first line isn't working for the first file only - but is for the others, any ideas?

   #!/bin/sh

cpuser=$1
cd "/home/$cpuser/public_html"

wpconfigs=($(find . -name "wp-config.php"))
for i in "${wpconfigs[@]}";

do
cpuser=$cpuser
wpdb=$(grep -e "DB_NAME" $i | cut -d \' -f 4)
wpuser=$(grep -e "DB_USER" $i | cut -d \' -f 4)
wppass=$(grep -e "DB_PASS" $i | cut -d \' -f 4)

set -x uapi --output=jsonpretty --user="$cpuser" Mysql create_user name="${wpuser}" password="${wppass}";
sleep 2s;
set -x uapi --output=jsonpretty --user="$cpuser" Mysql set_privileges_on_database user="${wpuser}" database="${wpdb}" privileges="ALL PRIVILEGES";
sleep 2s;
set -x uapi --output=jsonpretty --user="$cpuser" Mysql set_password user="${wpuser}" password="${wppass}";
sleep 2s;
done

When I look at the output run set -x to debug I see the following;

[root@cpanel201 ~]# sh ./testing.sh qv5goe35p3783sz8
+ sleep 2s
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql set_privileges_on_database 'user=qv5goe35p3783sz8_yscr_bbS$L5' database=qv5goe35p3783sz8_blog 'privileges=ALLPRIVILEGES'
+ sleep 2s
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql set_password 'user=qv5goe35p3783sz8_yscr_bbS$L5' password=FhtH6UztIuoS0_
+ sleep 2s
+ for i in "${wpconfigs[@]}"
+ cpuser=qv5goe35p3783sz8
++ grep -e DB_NAME ./wordpress/wp-config.php
++ cut -d \' -f 4
+ wpdb=qv5goe35p3783sz8_wordpress
++ grep -e DB_USER ./wordpress/wp-config.php
++ cut -d \' -f 4
+ wpuser=qv5goe35p3783sz8_yscr_bb5X8h
++ grep -e DB_PASS ./wordpress/wp-config.php
++ cut -d \' -f 4
+ wppass=X7lyC17Td8tH3cm
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql create_user name=qv5goe35p3783sz8_yscr_bb5X8h password=X7lyC17Td8tH3cm
+ sleep 2s
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql set_privileges_on_database user=qv5goe35p3783sz8_yscr_bb5X8h database=qv5goe35p3783sz8_wordpress 'privileges=ALL PRIVILEGES'
+ sleep 2s
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql set_password user=qv5goe35p3783sz8_yscr_bb5X8h password=X7lyC17Td8tH3cm
+ sleep 2s
+ for i in "${wpconfigs[@]}"
+ cpuser=qv5goe35p3783sz8
++ grep -e DB_NAME ./newsite/wp-config.php
++ cut -d \' -f 4
+ wpdb=qv5goe35p3783sz8_newsite
++ grep -e DB_USER ./newsite/wp-config.php
++ cut -d \' -f 4
+ wpuser=qv5goe35p3783sz8_yscr_bbxQiN
++ grep -e DB_PASS ./newsite/wp-config.php
++ cut -d \' -f 4
+ wppass=XpMa4v5z54tcM
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql create_user name=qv5goe35p3783sz8_yscr_bbxQiN password=XpMa4v5z54tcM
+ sleep 2s
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql set_privileges_on_database user=qv5goe35p3783sz8_yscr_bbxQiN database=qv5goe35p3783sz8_newsite 'privileges=ALL PRIVILEGES'
+ sleep 2s
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql set_password user=qv5goe35p3783sz8_yscr_bbxQiN password=XpMa4v5z54tcM
+ sleep 2s

If you look at the outputs for the second + third set of files you'll see three uapi commands, however, for the first we only see two and no outputs in terms of the greps it is doing on the top file.

For your reference, cpuser is set on the command line (the value after sh ./testing.sh)

I've also noticed that in the top file, the user appears to get surrounded by 's however the other two don't.

For clarity what the script is doing here;

  • Scraping any wp configs for a sql db name, db user and db password
  • Passing the user name and password to a cpanel api to create the user in a cPanel instance

The action works on config files 2 and 3 in this instance, but, not with the initial one - you will see the first create_user is missing even on the set -x

**

UPDATE

Having reviewed the logs, I believe this may be due to the fact that the user on the first one has a $ within it - could this be why? I have noticed that only on this one also, the command gets quoted within ''s which is incorrect for uapi. If this may be why, how do I resolve that?

'user=qv5goe35p3783sz8_yscr_bbS$L5'

How do I escape the $, as I think that's what is causing the issue in this case - all others are okay, only where a $ is within the username does this issue occur

  • 1
    Put a valid [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) and paste your script at https://shellcheck.net for validation/recommendation. Also a simple input and desired output would help others to understand what the actual goal is. – Jetchisel Feb 04 '23 at 12:43
  • Further details added @Jetchisel - the -x was just for me to see what was being pushed out – lukederbyshire Feb 04 '23 at 12:58
  • 2
    `set -x` is being used incorrectly. Either use it once by itself towards the start of the program, or invoke the program with `bash -x ...`. See [How can I debug a Bash script?](https://stackoverflow.com/q/951336/4154375). – pjh Feb 04 '23 at 13:03
  • The code is being run with `sh` (which may be `bash`, but could also be `dash` or something else) but uses bashisms (arrays). – pjh Feb 04 '23 at 13:05
  • `wpconfigs=($(find . -name "wp-config.php"))` doesn't work in general. If you run [Shellcheck](https://www.shellcheck.net/) on the code it will point out the problem, and link to explanations and options for fixing it. – pjh Feb 04 '23 at 13:07
  • I believe the issue is due to actually the user having a $ in it, however, I'm unsure if there is a way to pass it without having an issue. The rest of the array works perfectly fine, just this one with the $ is the username – lukederbyshire Feb 04 '23 at 13:08
  • 1
    Since uses of `$wpuser` are quoted, having a `$` in it should not be a problem. The output from `set -x` is confusing. It's trying to be helpful by only putting quotes where they would be needed if the command was run manually. The quotes are *not* passed to `uapi`. Your problem is almost certainly elsewhere. – pjh Feb 04 '23 at 13:13
  • All the semicolons in the code are redundant. They are harmless, but make it a little more difficult to read. – pjh Feb 04 '23 at 13:13
  • See [Bash Pitfalls #1 (for f in $(ls *.mp3))](https://mywiki.wooledge.org/BashPitfalls#for_f_in_.24.28ls_.2A.mp3.29) for more information on the problems with `$(find ...)`, including what to do about it. – pjh Feb 04 '23 at 13:16
  • 1
    Make sure none of the lines contains `CR` with dos2unix. – konsolebox Feb 04 '23 at 13:57
  • The issue only happens on the first line of the for - I think it's because the first wpconfig has a $ in the username so it's quoting that particular for in ''s, how do I escape them when it prints the variable ? – lukederbyshire Feb 04 '23 at 13:59
  • 1
    Also [How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?](http://mywiki.wooledge.org/BashFAQ/001) – chepner Feb 04 '23 at 14:30
  • Again, the `'` characters around the username are an artifact of `set -x`. To see what `uapi` is really seeing, temporarily put `echo` before it (`echo uapi --output=...`) and run the code. – pjh Feb 04 '23 at 14:36
  • I don't know what `uapi` does, but I guess that in this case it is running MySQL commands internally. It that is the case, I also guess that it may be causing an extra shell expansion to happen on the arguments. That would require embedding quotes in the strings passed to it. To reliably add quotes to the contents of `wpuser` run `printf -v wpuser '%q' "$wpuser"`. – pjh Feb 04 '23 at 14:50
  • 1
    See also [Difference between sh and bash](https://stackoverflow.com/questions/5725296/difference-between-sh-and-bash) – tripleee Feb 04 '23 at 14:50
  • Note that, with the current code in the question, `uapi` is never run. `set -x uapi --output=jsonpretty ...` turns on tracing (or leaves it on if it is on already) and then assigns `uapi` to positional parameter 1 (`$1`), assigns `--output=jsonpretty` to positional parameter 2 (`$2`), and so on. – pjh Feb 04 '23 at 15:00
  • If you fix the known problems with the code (bad `#!`, `set -x uapi ...`, [Shellcheck](https://www.shellcheck.net/) errors, ...) and run it, exactly what errors do you see? The only errors that I've seen described are relics of (incorrectly) using `set -x`. – pjh Feb 04 '23 at 15:03

1 Answers1

0

The follow code tells it all:

$ set -x ls
$ ls
+ ls
a.out    

As far as I know in all shells the 'ls' behind 'set -x' is ignored. By the next '$ ls' and '+ ls' you can see that 'set -x' is executed.

The normal way to do this, and probably what you want, is:

$ set -x 
$ ls
+ ls
a.out   
$ set -
+ set -  

Or as a one liner:

$ set -x ; ls ; set -
+ ls
a.out
+ set -    

By the previous you can also see why the line is missing in your output 'set -x' just enables shell tracing for the next command, where 'set -' ends it also for the next command.

dekerser
  • 51
  • 4
  • With `set -x ls` the `ls` is not ignored. Positional parameter 1 (`$1`) becomes `ls`. – pjh Feb 04 '23 at 17:24
  • Hi Dekerser, if I run without set -x at all, the error in the logs shows that the $ from the password is being transposed as a new variable and continuing through the script adding random ` before and after things. – lukederbyshire Feb 04 '23 at 20:04
  • First remark is of course correct $1 becomes 'ls'. Now it comes down to what you are doing with your script. But your 'set -x uapi ...' is just setting shell positional parameters so it is not doing anything. So overwriting positional parameters multiple times makes no sense, except perhaps for wrongly understood tracing information. Hence my above answer. – dekerser Feb 05 '23 at 12:42
  • The transposing of '$L5' in the user is normal shell behavior when the value is evaluated. To find where it is happening can be tricky. A generic escape is to replace '$' in de value with '\$'. Use '${cpuser//\$/\\$}' as a cure. But code like this is always dangerous as there are more shell characters that need escaping... To see what happens use 'eval echo $cpuser' and 'eval echo ${cpuser//\$/\\$}' – dekerser Feb 05 '23 at 13:03