I try to run the following bash script to create a bunch of users, groups, home dirs for the users and correct permissions for all of these. The OS is CentOS.
When I try to run the following, which I though should work, it returns "command not found" when running via terminal. it only gets as far as creating the /homedirs directory, nothing more. I'm a total noob at bash scripting so forgive me if this looks ugly.
mkdir /homedirs; chmod 775 /homedirs;
for iYear in {1..3} do
sYear = $iYear"ti"
sYearDir = "/homerirs/"$sYear
groupadd $sYear; mkdir $sYearDir; chgrp $sYear $sYearDir; chmod 750 $sYearDir
for sClass in {a,b} do
sClassDir = $sYearDir/$sClass
mkdir $sClassDir
sClassGrp = $sYear$sClass
groupadd $sClassGrp; chgrp $sClassGrp $sClassDir; chmod 750 $sClassDir
for iUser in {1..3} do
sUserName = "i"$iYear$sClass"g"$iUser
sUserDir = $sClassDir/$sUserName
useradd -d $sUserDir -g $sClassGrp -G $sYear -m $sUserName
chown $sUserName $sUserDir; chmod 750 $sUserDir
done
done
done
The error message is caused by the spaces around the equals signs. A token with whitespace after it is interpreted as a command name; so what you intended as variable names causes the Command not found errors.
You may need to set your PATH and you really should read the advanced bash scripting guide. See also this answer.
I also suggest to debug your script by starting it with #!/bin/bash -vx as its first line. And you should make it executable with chmod u+x at least.
Perhaps groupadd might not be available on your system.
best thing to do is add the full path before your executables:
change useradd to /usr/sbin/useradd
change groupadd to /usr/sbin/groupadd
will cure the command not found.
remember this programs will probably need to run as root to work.
Related
I am running a bash script and these commands in the script will not work without sudo in front of them. The script.sh is located in a folder such as /jobs/script.sh
Example of commands I am trying to run in the script.sh -
mv /var/app/myapp /var/app/myapp.old
rm file.tar.gz
tar -xzf /home/ubuntu/file.tar.gz -C /var/app/
All the above work if I add sudo in front of them.
I am trying to figure out what permissions are required for them to work without adding sudo in the script.
I have tried giving the script.sh rwx permissions and changing owner to root.
I'm learning permissions in linux, so I'm new to this. Basically what permission should the script.sh have so that I dont have to use sudo in the bash file? Any insight would greatly help.
When you run sudo <some command>, then <some command> is run by the root user (Super user do). The reason you might need to run any command using sudo is because the permissions on the files that command reads/writes/executes are such that only the "Super user" (root) has that permission.
When executing the command mv fileA fileB, the executing user would need:
Write permission to fileB if fileB already existed
Write permission to the directory containing fileB
From what you said it’s most likely you want read and write permissions you can achieve this with chmod
Chmod +[permission] filename
(+ is used to add permission you can also use - instead to remove it)
Where permissions can be:
r —> read
w—> write
x —>excecute
... and more
FOR EXAMPLE: it seems you write permissions for the first file so :
chmod +w /var/app/myapp
Will fix problem
I have to run a command in a script as a non-root user, or the command won't run. However once this is done, I need the subsequent file to be chown'd to the root user. However, I'm not sure what is the "correct" or best method of doing this.
Sample:
sudo -u $usr db export --path="${htmldir}"/ "/home/zzz/backups/${url}_${st}_$(date '+%Y-%m-%d-%H-%M-%S').sql"
Basically the above has various variable substitutions. I'm also adding a timestamp to the file. What would be the best way to chown that file that has just been created, as it has a timestamp - which could be different if I ran a:
chown root:root "/home/zzz/backups/${url}_${st}_$(date '+%Y-%m-%d-%H-%M-%S').sql"
How do I run a command and place part of that command in a variable - the output file name?
You should only run the date command once, and store the result in a variable. You could either store just the date:
curr_date="$(date '+%Y-%m-%d-%H-%M-%S')"
sudo -u $usr db export --path="${htmldir}"/ "/home/zzz/backups/${url}_${st}_${curr_date}.sql"
chown root:root "/home/zzz/backups/${url}_${st}_${curr_date}.sql"
...or save the entire file path in a variable:
sql_file="/home/zzz/backups/${url}_${st}_$(date '+%Y-%m-%d-%H-%M-%S').sql"
sudo -u $usr db export --path="${htmldir}"/ "$sql_file"
chown root:root "$sql_file"
Personally, I'd prefer the second since it makes it clearer that it's the same file in both places (and harder to goof and use different paths in the two commands). If you needed to use the date for something else as well, I'd actually recommend storing both:
curr_date="$(date '+%Y-%m-%d-%H-%M-%S')"
sql_file="/home/zzz/backups/${url}_${st}_${curr_date}.sql"
sudo -u $usr db export --path="${htmldir}"/ "$sql_file"
chown root:root "$sql_file"
someotherCommand "$curr_date"
Oh, and double-quoting the string on the right side of an assignment is optional, but in lots of other contexts using a variable without double-quotes around it can cause trouble, so I tend to double-quote in assignments just for consistency.
You don't need to use sudo to run the command since you are already root
su -l user -c "db export --path=${htmldir}/ /home/zzz/backups/${url}_${st}_${curr_date}.sql"
chown root:root /home/zzz/backups/${url}_${st}_$(date '+%Y-%m-%d-%H-%M-%S').sql
I am trying to set up a cron on several AWS EC2 machines and would like to run a command on all of them at once, with the following shell script:
#!/bin/sh
cd /etc/cron.daily
touch ecs.sh
echo '#!/bin/sh' > /etc/cron.daily/ecs.sh
echo 'sudo yum update -y ecs-init' >> /etc/cron.daily/ecs.sh
echo 'sudo yum update -y' >> /etc/cron.daily/ecs.sh
sudo chmod 755 /etc/cron.daily/ecs.sh
cd ~
(crontab -u root -l; echo '0 0 * * * /etc/cron.daily/ecs.sh') | crontab -u root -
sudo yum update -y
The part that does not work is: chmod 755 /etc/cron.daily/ecs.sh
I am not sure, what am I missing.
If you can (have sufficient rights to) create a file, you do not need to sudo to change its permissions to 0755. Which would also likely prompt you to input your password and run non-interactively could be the reason why the action did not take place.
On the other hand, if the user running this did not have the necessary (write) permission, preceding lines creating the file would not happen either.
You also do not need to touch a file, because that > redirection will create it (always a new one).
You also should not cd somewhere and and continue performing actions without checking directory was changed as expected. But since on all action but the unnecessary touch you use absolute path names, you can just as well leave out both cd lines.
If you clean-up the script and it still does not perform expected action, it might be useful (assuming non-interactive execution) to save its output (redirect both standard > (or 1>) and error (2>) output to a file) and examine it for errors.
I have a bash script that partially needs to be running with default user rights, but there are some parts that involve using sudo (like copying stuff into system folders) I could just run the script with sudo ./script.sh, but that messes up all file access rights, if it involves creating or modifying files in the script.
So, how can I run script using sudo for some commands? Is it possible to ask for sudo password in the beginning (when the script just starts) but still run some lines of the script as a current user?
You could add this to the top of your script:
while ! echo "$PW" | sudo -S -v > /dev/null 2>&1; do
read -s -p "password: " PW
echo
done
That ensures the sudo credentials are cached for 5 minutes. Then you could run the commands that need sudo, and just those, with sudo in front.
Edit: Incorporating mklement0's suggestion from the comments, you can shorten this to:
sudo -v || exit
The original version, which I adapted from a Python snippet I have, might be useful if you want more control over the prompt or the retry logic/limit, but this shorter one is probably what works well for most cases.
Each line of your script is a command line. So, for the lines you want, you can simply put sudo in front of those lines of your script. For example:
#!/bin/sh
ls *.h
sudo cp *.h /usr/include/
echo "done" >>log
Obviously I'm just making stuff up. But, this shows that you can use sudo selectively as part of your script.
Just like using sudo interactively, you will be prompted for your user password if you haven't done so recently.
I have a php page.
It calls a validation bash script that checks variables passed from the php page.
I then call another bash script that I need to execute under root user. I have followed the guide here How to run from PHP a bash script under root user and still can not get script to execute as root.
I have the following:
php page
$bashFile = shell_exec('./Validation.sh "'.$coinName.'" "'.$coinNameAbreviation.'" "'.$blockReward.'" "'.$blockSpacing.'" "'.$targetTimespan.'" "'.$totalCoins.'" "'.$firstBitAddy.'" "'.$seedNode.'" "'.$seedName.'" "'.$headline.'" ');
echo "<pre>$bashFile</pre>";
the validation file:
sudo nohup /bin/bash /usr/sbin/CoinCreationBashFile "$coinName" "$coinNameAbreviation" "$blockReward" "$blockSpacing" "$targetTimespan" "$totalCoins" "$firstAddyBit" "$seedNode" "$nameSeedNode" "$headline" "$blocksPerDay" "$startingDifficulty" >> /tmp/BASH2log.txt 2>&1 &
I have added
www-data ALL=NOPASSWD /usr/sbin/CoinCreationBashFile
to the end of the sudo visudo
and did:
chown root:root /usr/sbin/CoinCreationBashFile
chmod 755 /usr/sbin/CoinCreationBashFile
was running it from usr/sbin from suggestion here http://ubuntuforums.org/showthread.php?t=1848069
Can anyone see what I am doing wrong?? Many thanks
edit: I can run the CoinCreationBashFile script without the sudo command and it runs ok up to one point where it needs root priv... so i know the script working, and executing from the terminal the script runs perfectly as desired. output in tmp/BASH2log.txt
sudo: no tty present and noaskpass program specified
This question is similar to sudo in php exec() and they did not arrive at a conclusion.
In your case, since only one bash script needs to be executed in this fashion, considering using setuid instead:
$ su
[enter password]
chown root:root something.sh
chmod 4755 something.sh
exit
Note: Some Linux distributions disable setuid for shell scripts by default for security reasons.
Update: Apparently no commonly used Linux distribution today allows setuid on shell scripts. Perl used to be the exception, but suid-perl is now deprecated.
The only way to execute your bash script using this method is to invoke it from a compiled binary. See the example with the C code on how to do this.
I recently published a project that allows PHP to obtain and interact with a real Bash shell, you can easily get a shell with root. Get it here: https://github.com/merlinthemagic/MTS
After downloading you would simply use the following code:
$shell = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
$strCmd = "/usr/sbin/CoinCreationBashFile ".$coinName." ".$coinNameAbreviation." ".$blockReward." ".$blockSpacing." ".$targetTimespan." ".$totalCoins." ".$firstAddyBit." ".$seedNode." ".$nameSeedNode." ".$headline." ".$blocksPerDay." ".$startingDifficulty." >> /tmp/BASH2log.txt 2>&1 &";
$return1 = $shell->exeCmd($strCmd);
//if there is any return from the script you can wait for the return
//or you can trigger like you have it now and get no return.
You have a typo in visudo entry. There is no R in the NOPASSWD. It should be:
www-data ALL=NOPASSWD /usr/sbin/CoinCreationBashFile