Same bash script has different behavior in 2 separate scripts. Thoughts?
Hey guys,
So I've been working on a really large project for work and I can't seem to crack this bug right now... So I'm trying to get my script to verify all users' home directories exist, using the following code: Code:
#!/bin/bash Code:
The home directory (HOME_DIR_PATH) of user USERNAME does not exist. Code:
The home directory () of user does not exist. Your help matters a ton! Thx :) |
It is because you're piping into your while loop at the beginning rather than redirecting at the end. With the pipe the variables are local and can't be used elsewhere such as within a function.
Code:
while read -r user dir The second less than is "process substitution" based on the grep - you may need to encapsulate the grep and what follows in parentheses for it work. |
Thanks! This seems to work, I'll bump the thread if this part of the function throws any more errors.
|
I would prefer pure shell builtins
Code:
# The following line is clumsy |
EDIT: still doesn't work
I tried both of the methods, and apparently it's still not working in my test lab vm. I'm beginning to wonder if it's an environment thing with CentOS 8... Because it worked at home.
|
The version MadeInGermany posted is definitely clearer.
It also makes it easy to add debug statements in, to test at which point things are differing from expectations... |
when you use pipe in shell scripts you will automatically force bash to use child processes.
So all your awk/grep/... will run in a new shell, but also your while loop will be put in a subshell. Additionally post #2 looks incorrect without parenthesis: Code:
while read -r user dir (this is just a comment: this grep and awk can be combined into one single awk) |
If you just copied the MadeInGermany's version without checking the syntax, be aware that there's a typo in the second case statement:
contine → continue |
I have to say that on any relatively new system, I feel as though there are plenty of issues to be had with some of the items in this script.
Specifically: 1. Many systems these days have /bin, /sbin and /usr/sbin as symbolic links to /usr/bin. Now depending on your PATH value, which will return the first place it finds any command. So using 'which nologin' is erroneous at best, here's an example on my home machine: Code:
$ echo $PATH 2. /bin/false -- see above as users could have /sbin/false, /usr/bin/false and /usr/sbin/false ... again, should you be limiting yourself? 3. grep -E -v '^(halt|sync|shutdown)' -- what if you have a user that starts with one of these words but has additional characters? (eg. sync-backup) 4. Try not to string multiple commands together when you are doubling up on abilities As you have a solution in all bash, here's another alternative in awk: Code:
awk -F: '$1 !~ /^(halt|sync|shutdown)$/ && $7 !~ /(nologin|false)/ && system("[[ -d "$6" ]]"){print "tada -- "$0}' /etc/passwd |
What do you mean by not work? What is your test lab VM?
I don't have CentOS 8 installed yet but the only difference I noticed with MadeInGermany's script as compared to CentOS 7 is which nologin returns /usr/sbin/nologin but /etc/passwd uses /sbin/nologin for a regular user. By default which (without any options) returns the first match and with CentOS7 /usr/sbin is in the path before /sbin for a regular user. So yes it could be an environment thing. I would not use a variable named dir since it is an actual command but that does not seem to break the script. A bit to late grail beat me to the punch... |
If there is a function called 'read' in the script it will replace the shell builtin and could cause an infinite loop.
Code:
read () { There is a missing parenthesis Code:
"$which nologin)" |
My test lab vm is a fresh CentOS 8 server install, and my home CentOS 8 vm is the same exact thing. I just tried grail's solution and it didn't work either... I just get the same infinite loop.
It's important to stress that my code already works, even if it's not proper. It's just not working inside CentOS 8 when paired with other bash functions I have defined, which is the intended goal. I'm throwing it into a function and calling it from another one, because that's what my script needs to do. I can run all this and have it work in the shell, or when I throw this portion of the bash script into it's own script it runs fine- but I cannot invoke it from my main script. That's what I'm trying to understand. Thanks again for your help! This problem has stumped my coworkers too... Should I try it on a different distro like debian and see if it's just a problem with my code? |
this is not related to the distro, although it may depend on the version of some tools you use (for example bash).
I would suggest you: 1. add set -xv to see what's happening - and try to post some debug output. Probably helps 2. try shellcheck, it can be useful too. 3. also would be nice to prepare a sample script to demonstrate what works and what failed. If we could try it we could also repair it. |
Here I avoid the problematic which
Code:
# for debugging uncomment the next line |
Quote:
I would suggest you review the Site FAQ for guidance in posting your questions and general forum usage. Especially, read the link in that page, How To Ask Questions The Smart Way. The more effort you put into understanding your problem and framing your questions, the better others can help! |
All times are GMT -5. The time now is 03:32 PM. |