Running Bash Script as root with non root script section

I have a bash script that needs to run as root to accomplish a task in this case it is to make the validator take a snapshot of the Helium blockchain.

I have edited the /etc/sudoers file to allow me to run this script as root. This works fine.

useraccount ALL=(ALL:ALL) NOPASSWD:/home/useraccount/validator_data/snapshotmaker.sh

The command in the script is as follows:

sudo docker exec validator miner snapshot take /var/data/$dtt

after this, the command generates a file like this '30-10-2021T233752.bin'.

My next step is to take this file and copy it to IPFS so I can share it. The command to do this is:

ipfs files cp /ipfs/$(ipfs add -Q $localfile) $ip

At the moment I get the following error:

Error: no IPFS repo found in /root/.ipfs. please run: 'ipfs init'

This is because it is trying to run it as root when the configuration is in my useraccount.

I have tried to switch accounts in the middle of the script but it seems to kill it.

So my question is how to run the IPFS command as my original user from within the root script.

My Bash Scrip:

#!/bin/bash
dt=$(date '+%d-%m-%YT%H%M%S');
dtt="${dt}.bin"
a='/var/data/'
c="${a}${dt}.bin"
echo "${c}"
sudo docker exec validator miner snapshot take /var/data/$dtt
localfile="/home/useraccount/validator_data/${dt}.bin"
echo "LocalFile: ${localfile}"
ip=" /Helium/Snapshots/2021/${dt}.bin"
echo "IPFS Location: ${ip}"
sleep 2
if [ -f "$localfile" ]; then echo "$localfile exists." sudo chown useraccount $localfile whoami su - useraccount whoami ipfs files cp /ipfs/$(ipfs add -Q $localfile) $ip #ipfs files cp /ipfs/$(ipfs add -Q <local-file>) "/Helium/Snapshots/2021/<dest-name>"
else echo "$localfile does not exist."
fi

The output is as follows:

/var/data/31-10-2021T005728.bin
ok
LocalFile: /home/useraccount/validator_data/31-10-2021T005728.bin
IPFS Location: /Helium/Snapshots/2021/31-10-2021T005728.bin
/home/useraccount/validator_data/31-10-2021T005728.bin exists.
root

And then it dies. If I remove the su line then I get the root issue as mentioned at the top of this post.

Hoping someone can help.

10

3 Answers

I made a 'dry run' test without docker and whatever you do in it and without ipfs. The method should work for you with the real programs after some tweaks.

  • Run the shellscript scrip as your normal user, not with sudo.

  • Edit the script to change from 'tester' in my demo to your user-name.

  • Edit the exact command lines that need sudo without password with visudo,

    $ LANG =C sudo tail -n2 /etc/sudoers
    %tester ALL=NOPASSWD: /usr/sbin/docker exec validator miner snapshot take /var/data/tmpfil
    %tester ALL=NOPASSWD: /usr/bin/chown tester /home/tester/validator_data/tmpfil
    • It is important to have a fixed name of the file for the sudo operations. After that it can be given a name that depends on the time.
    • Check the location of the docker executable (maybe not in /usr/sbin).

My modified script scrip:

#!/bin/bash
if [ "$(whoami)" != "tester" ]
then echo "run as 'tester'" exit
fi
dt=$(date '+%d-%m-%YT%H%M%S');
dtt="${dt}.bin"
a='/var/data/'
c="${a}${dt}.bin"
echo "${c}"
sudo /usr/sbin/docker exec validator miner snapshot take /var/data/tmpfil
if [ -f "/home/tester/validator_data/tmpfil" ]; then ls -l "/home/tester/validator_data/tmpfil" sudo /usr/bin/chown tester "/home/tester/validator_data/tmpfil" mv "/home/tester/validator_data/tmpfil" "/home/tester/validator_data/${dt}.bin" localfile="/home/tester/validator_data/${dt}.bin" echo "LocalFile: ${localfile}" ls -l "${localfile}" ip=" /Helium/Snapshots/2021/${dt}.bin" echo "IPFS Location: ${ip}" sleep 2 echo "$localfile exists." whoami /usr/local/bin/ipfs files cp /ipfs/$(/usr/local/bin/ipfs add -Q $localfile) $ip #ipfs files cp /ipfs/$(ipfs add -Q <local-file>) "/Helium/Snapshots/2021/<dest-name>"
else echo "$localfile does not exist."
fi

A script pretending to be the docker command line:

#!/bin/bash
if [ "$EUID" == "0" ]
then echo "docker's world" > "/home/tester/validator_data/tmpfil" chown root:root "/home/tester/validator_data/tmpfil" echo "ok"
else echo "run with sudo"
fi

Demo run:

tester@lenovo-v130:~$ LANG=C ./scrip
/var/data/01-11-2021T051748.bin
ok
-rw-r--r-- 1 root root 15 Nov 1 05:17 /home/tester/validator_data/tmpfil
LocalFile: /home/tester/validator_data/01-11-2021T051748.bin
-rw-r--r-- 1 tester root 15 Nov 1 05:17 /home/tester/validator_data/01-11-2021T051748.bin
IPFS Location: /Helium/Snapshots/2021/01-11-2021T051748.bin
/home/tester/validator_data/01-11-2021T051748.bin exists.
tester
./scrip: line 34: ipfs: command not found
./scrip: line 34: ipfs: command not found
4

So my question is how to run the IPFS command as my original user from within the root script.

sudo su - useraccount -c COMMAND

First, you need to create a sudo configuration for your script, in this example, we place it in /etc/sudoers.d with permission 440:

Cmnd_Alias CMDS = /opt/bin/docker_example.sh
User_Alias CMDUSERS = bac0n
CMDUSERS ALL=(ALL) NOPASSWD: CMDS
Defaults!CMDS !requiretty

We name the script docker_example.sh, as shown in the sudo example:

#!/bin/bash
# Exit immediately on non-zero exit status.
set -e
((EUID != 0)) && { echo This script should run as root. exit 1
}
[[ ${SUDO_USER+ } ]] && \
user_account=$SUDO_USER || user_account=$(id -nu)
printf -v bin_file \
'%(%d-%m-%YT%H%M%S)T.%s' -1 bin
local_file=$HOME/validator_data/$bin_file ipfs_file=/Helium/Snapshots/2021/$bin_file
printf '
Bin File: %s
Local File: %s
IPFS File: %s
' "$bin_file" "$local_file" "$ipfs_file"
docker exec validator miner snapshot take "/var/data/$bin_file"
sleep 2
[[ -f $local_file ]] || { echo File does not exist: "$local_file" exit 1
}
chown $user_account "$local_file"
#
# su $user_account -c 'echo whoami: $1, su: $(id -nu)' _ $(id -nu)
#
su $user_account -c 'ipfs files cp "/ipfs/$(ipfs add -Q "$1")" "$2"' _ "$local_file" "$ipfs_file"

Now you should be able to add this script with sudo to crontab, and it should run with NOPASSWD.

$ sudo crontab -u bac0n -e
# min hour dom month dow command
* * * * * sudo /opt/bin/docker_example.sh > /dev/null 2>&1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like