How to implement an "Are you root?" test in a shell script

About writing shell scripts and making the most of your shell
Forum rules
Topics in this forum are automatically closed 6 months after creation.
jharris1993
Level 3
Level 3
Posts: 188
Joined: Mon Nov 05, 2012 9:43 pm
Location: Worcester Ma. (USA) when I'm not in Moscow Russia
Contact:

How to implement an "Are you root?" test in a shell script

Post by jharris1993 »

Greetings!

One of the things I do is to create - and destroy! - Linux systems on a regular basis, and invariably there are a number of stupid and annoying things that I always want to configure prior to actually starting to USE the system.

To solve this problem, I wanted to create a "system customization" script that I could drop in and run on any Ubuntu/Mint based system I create. The sticking point is that in order to work properly, it needs to run as root since it installs, slices, dices, and makes modifications to the basic system. :shock:

Since it only needs to run once after the initial install of the system, it didn't make sense to install it in /usr/bin, or run it as a cron job, as some suggested. Others suggested writing it in Perl, Python, C, or whatever. Sheesh! All I wanted to do was have the script execute a simple "Am I being run as root, or not?" test.

I searched the Web and found nothing on the subject of "How do you implement a test for "Am I root?" in a shell script.

I knew it could be done since there are only about ten-zillion scripts that make the "are you root?" test. So I fussed with it, wrote some sample scripts, made absolutely hideous mistakes, and then came up with an answer that worked.

The result of this is the following snippet of code:

Code: Select all

#!/bin/bash

# I'm using bash so that line feeds work properly.  If they don't, add "/n" to the end of each line.
#  ---- add additional comments, or code, here ----

# Check if I am root.  If not, print an explanatory error and exit

myname=`whoami`
if [ $myname != "root" ]; then
   echo "
Oops! This script needs to be run as root, but you are logged in as \""$myname"\"
Try running the script again with \"sudo\" like this:
sudo [this script's name]
"
    exit 1
fi

# We're running as root, so let's go!

#  ---- insert rest of script here ----
Hopefully this will help other newbie script writers handle the test for "am I root?" in a script.

What say ye?

Jim (JR)
Jim "JR"

Some see things as they are, and ask "Why?"
I dream things that never were, and ask "Why Not".

Robert F. Kennedy

“Impossible” is only found in the dictionary of a fool.
Old Chinese Proverb
User avatar
GlennJohnson
Level 2
Level 2
Posts: 51
Joined: Mon Dec 07, 2009 7:24 pm
Location: Haverhill, Mass

Re: How to implement an "Are you root?" test in a shell scri

Post by GlennJohnson »

Here's another:

Code: Select all

if [[$EUID -ne 0 ]] ; then
        printf "Please execute this script with root permissions\n"
        exit 1
fi
dorian_mode

Re: How to implement an "Are you root?" test in a shell scri

Post by dorian_mode »

[Oops! This script needs to be run as root, but you are logged in as \""$myname"\"
Try running the script again with \"sudo\" like this:
sudo [this script's name]
"
exit 1
fi

# We're running as root, so let's go!

# ---- insert rest of script here ----]

Am I missing something here? All this is doing is using the sudo command to borrow root privileges, or you could log in as sudo -i
which lets you log in as root (within the preset limits allowed by system security).
jharris1993
Level 3
Level 3
Posts: 188
Joined: Mon Nov 05, 2012 9:43 pm
Location: Worcester Ma. (USA) when I'm not in Moscow Russia
Contact:

Re: How to implement an "Are you root?" test in a shell scri

Post by jharris1993 »

Dorian,

Allow me to apologize if my message was not clear.

The idea of this message was to provide a way - within the context of a user generated shell script to implement a test for root privilege.

Admittedly, the majority of scripts written by users will ether not require root privileges at all, or will be something run so regularly that it is worthwhile to place it in the startup scripts, or create a CRON job for it. Both of which automatically run as root.

In my case, since I am often creating systems - for whatever reason - and I (almost) always configure them the same way every time, it is a pain for me to have to remember what, when, and how to configure the system to my liking. Because my script creates, modifies, and installs things - it needs to be run as root.

I am sure that other users may wish to - on occasion - write scripts that need to be run as root. It is convenient to have the script test if root privilege has been granted prior to running the commands in the script and generating a bunch of bogus errors due to the lack of elevated privilege.

An example of this is the "e2fsck" command. If you try to run it as a non-privileged user, it generates a simple error: "you must be root."

Since I had not seen any suggestions on how this is done, I wrote a simple test for root privilege. If you are root, or have sudo'd to root, it runs normally, If you have not acquired root privilege, either by elevation of privilege, or by running in a root-shell, it tells you what is wrong, and suggests a solution to solve the problem.

What say ye?

Jim
Jim "JR"

Some see things as they are, and ask "Why?"
I dream things that never were, and ask "Why Not".

Robert F. Kennedy

“Impossible” is only found in the dictionary of a fool.
Old Chinese Proverb
dorian_mode

Re: How to implement an "Are you root?" test in a shell scri

Post by dorian_mode »

Thank you for the clarification. I admire anyone who likes to tinker or try geeky things the way you do. I do myself, but not to the same degree of proficiency that you have. Actually this is one of the things I like about Linux. It is also one of the reasons I like Slackware, I don't have to struggle through all the restrictions ubuntu has in order to have root privileges.
User avatar
Pilosopong Tasyo
Level 6
Level 6
Posts: 1432
Joined: Mon Jun 22, 2009 3:26 am
Location: Philippines

Re: How to implement an "Are you root?" test in a shell scri

Post by Pilosopong Tasyo »

Yet another way using the $USER environment variable:

Code: Select all

administrator@dg31pr:~/Desktop$ cat > r-ya-root ; chmod +x r-ya-root
#! /bin/bash

[ "$USER" = "root" ] && echo "You got root powers" || echo "Just a regular user"

administrator@dg31pr:~/Desktop$ ./r-ya-root 
Just a regular user

administrator@dg31pr:~/Desktop$ sudo ./r-ya-root 
[sudo] password for administrator: 
You got root powers
o Give a man a fish and he will eat for a day. Teach him how to fish and he will eat for a lifetime!
o If an issue has been fixed, please edit your first post and add the word [SOLVED].
jharris1993
Level 3
Level 3
Posts: 188
Joined: Mon Nov 05, 2012 9:43 pm
Location: Worcester Ma. (USA) when I'm not in Moscow Russia
Contact:

Re: How to implement an "Are you root?" test in a shell scri

Post by jharris1993 »

@ all posters

These are all excellent ideas for solving a test for root privilege. I hope the mod's leave this open for a while longer - hopefully it will generate more, similarly excellent replies.

Thanks to everyone who has posted!

Jim (JR)
Jim "JR"

Some see things as they are, and ask "Why?"
I dream things that never were, and ask "Why Not".

Robert F. Kennedy

“Impossible” is only found in the dictionary of a fool.
Old Chinese Proverb
jharris1993
Level 3
Level 3
Posts: 188
Joined: Mon Nov 05, 2012 9:43 pm
Location: Worcester Ma. (USA) when I'm not in Moscow Russia
Contact:

Re: How to implement an "Are you root?" test in a shell scri

Post by jharris1993 »

dorian_mode wrote: It is also one of the reasons I like Slackware, I don't have to struggle through all the restrictions ubuntu has in order to have root privileges.
Dorian,

Huh? What restrictions? "sudo" (AFAIK) has been a standard shell command since about five minutes after the creation of Oxygen in the atmosphere. :D

Acquiring more extensive root privilege in a terminal session only requires running the terminal itself as root. Additionally, things like your desktop's file manager can be run as root - along with other programs that get pissy (or have limited functionality) if not run as root.

Pretty much every system I use runs Grub, or a Grub clone, (Cinnamon, Mate, etc.), so I can use the command "gksu" to force something to request root privilege. Other desktops probably have similar commands, I just don't know what they are.

Example: Assume there is a terminal emulator called "SuperTerminal" and does all kinds of things like falling snowflakes in the background, etc. If you place a copy of the program's icon on your desktop, (because you use it all the time!), right click on it to call up it's property sheet, you will notice that the command is something like:

Code: Select all

superterm
If you edit this to say:

Code: Select all

gksu superterm
causes this icon - when clicked - to pop-up the request for root privilege dialog. Once you enter your password you get a SuperTerminal running as root.

In my case, I use the terminal fairly often. The vast majority of the time I have no real need for root privilege, or it is so limited that I can use "sudo" to get it. However, there are times when I am going to be doing a lot of work as "root" at the same time, and typing "sudo" a half-a-zillion times is a Royal Pain In The Tush. In those cases I use a "root" terminal. I have a standard terminal on my desktop, and a root terminal in a special "Administrative Tools" folder that I created. (That also has a number of other tools I like to run as root - synaptic, gparted, etc.)

I have run Slackware, (and, frankly, I was not impressed - but that's me), Fedora, and a couple of others I don't remember right now. In every case, getting root privilege was no more difficult in any one distribution than in any of the others.

The big usability problem that I have found is not necessarily the distribution but is the desktop you use. I have tried, (for example), KDE, and found it very difficult to work with, no matter what I tried to do. Again, that's my opinion, Your Mileage will most certainly Vary. (BTW, despite the fact that I use Gnome clones, I always download "kuser" because gnome's user editor sucks hugely.)

What say ye?

Jim (JR)
Jim "JR"

Some see things as they are, and ask "Why?"
I dream things that never were, and ask "Why Not".

Robert F. Kennedy

“Impossible” is only found in the dictionary of a fool.
Old Chinese Proverb
Arikania

Re: How to implement an "Are you root?" test in a shell script

Post by Arikania »

Root always has user ID 0. That is the most reliable check I think.

Code: Select all

#! /bin/bash

[ $UID == 0 ] && p="indeed" || p="NOT"
printf "You are $p root\n"

[ $XAUTHORITY ] && p="X" || p="tty"
printf "You are in $p mode\n"

echo
echo Have a nice day!

Kindly,
User avatar
austin.texas
Level 20
Level 20
Posts: 12003
Joined: Tue Nov 17, 2009 3:57 pm
Location: at /home

Re: How to implement an "Are you root?" test in a shell script

Post by austin.texas »

Great suggestions by Pilosopong Tasyo and Arikania !

@ jharris1993 - I have created my own scripts which configure a new installation for me, just as you are doing. You might steal some ideas from them, also.
In order to "clone" my Mint 17.2 Cinnamon to a new Mint 17.3 Cinnamon installation on a different computer, I created two scripts to automate what I usually do manually.
I again used these scripts to "clone" my configuration from Mint 17.3 to Mint 18, then from Mint 18 to 18.1 They save me a lot of time!

The first script (backup.sh) backs up my current configuration.
The second script (update.sh) installs my configuration to the new computer.

backup.sh

Code: Select all

#!/bin/sh
# You will need a backup drive with at least 1GB available.
# Boot into the OS that you want to back up.
# make a folder on your backup drive "backupscript"
# save this file in the backupscript folder, as backup.sh
# right-click on the backupscript folder & open a terminal
# make the script executable with "sudo chmod u+x backup.sh"
# run the script with "sudo ./backup.sh"

# clean out unneeded .deb files:
aptitude autoclean
# copy all remaining .deb files - 
# this eliminates excessive downloading when installing your programs
mkdir archives
cp -n /var/cache/apt/archives/*.deb ./archives/

# copy the software sources so that the PPA's can be restored
cp -a /etc/apt .

# backup all repository keys - optional. Use only when cloning the same version !
# apt-key exportall > repo.keys

# I have customized grub config files that I want to preserve:
cp /etc/default/grub .
cp /etc/grub.d/40_custom .
cp /etc/grub.d/06_mint_theme .
cp /boot/grub/161807-neblu.jpg .
cp /etc/sudoers.d/dan .

# copy personal configuration and program configs
# if you use Firefox or Thunderbird you will want to add those to this list
# any programs you don't use can be deleted from this list
cp -a $HOME/.avidemux .
cp -a $HOME/.gconf .
# I have my chosen program launchers in .config/autostart
cp -a $HOME/.config/autostart .
cp -a $HOME/.config/Pinta .
cp -a $HOME/.config/geany .
cp -a $HOME/.config/puddletag .
cp -a $HOME/.config/roxterm.sourceforge.net .
cp -a $HOME/.config/smplayer .
cp -a $HOME/.config/vlc .
cp -a $HOME/.config/clipit .
cp -a $HOME/.filezilla .
cp -a $HOME/.grsync .
cp -a $HOME/.icons .
cp -a $HOME/.local .
cp -a $HOME/.multisystem .
cp -a $HOME/.openshot .
cp -a $HOME/.themes .
cp -a $HOME/.wallpapers .
# preserve my clock display config
cp -a $HOME/.cinnamon/configs/clock@cinnamon.org .
cp -a $HOME/.mozilla/seamonkey .
cp -a $HOME/.asunder* .
cp -a $HOME/.bash_history .
# preserve my custom aliases in bashrc
cp -a $HOME/.bashrc .
cp -a $HOME/.face .
cp -a $HOME/.gimp-2.8 .
cp -a $HOME/.gnupg .
cp -a $HOME/.config/google-chrome .
cp -a $HOME/bin .
cp -a $HOME/Templates .

# remove Firefox and Thunderbird
# I don't use them, and don't want frequent updates
apt-get --purge autoremove -y firefox  firefox-locale-en
apt-get --purge autoremove -y thunderbird  thunderbird-gnome-support

# save installed software list
# WARNING "dpkg set-selections" should be used ONLY when migrating to the SAME version and desktop !!!
# otherwise you will trash the new system - at least that is my experience...
# See https://forums.linuxmint.com/viewtopic.php?f=47&t=169573#p872138
# as to why "dpkg set-selections" is probably not a good idea for Mint at all
# for one thing it will list all the installed kernels, and possibly obsolete library files
# It is better to manually maintain a list of the programs you want to install.
dpkg --get-selections > installed-software.list

# If you want to use "dpkg set-selections" to restore the listed programs, 
# you need to edit the installed-software.list file to delete all lib* and linux* references. 
# You don't want to install obsolete libraries or kernels. 
# In fact, delete all programs you don't recognize.
# You can get a nice list of the installed programs with short descriptions (for reference), with the command: 
# dpkg -l | grep ii >> installed-programs.list

# backup the entire Cinnamon dconf
# includes the menu favorites, panel location, hot corners, etc.
dconf dump /org/cinnamon/ > dconf.org.cinnamon

# backup the entire Nemo dconf
# preserves columns, views, and Desktop
dconf dump /org/nemo/ > dconf.org.nemo

echo DONE !
update.sh

Code: Select all

#!/bin/sh
# save this file in the backupscript folder as update.sh
# make it executable with "sudo chmod u+x update.sh"
# boot into the newly installed OS
# establish wireless or cable internet connection
# Check Software Sources for fastest connection 
# right-click on the backupscript folder & open a terminal
# run the script with "sudo ./update.sh"

echo Did you check Software Sources for the fastest connection?
while true
do
  echo -n "Enter y(es) to continue or n(o) to abort:"
  read CONFIRM
  case $CONFIRM in
    y|Y|YES|yes|Yes) break ;;
    n|N|no|NO|No)
      echo Aborting - you entered $CONFIRM
      exit
      ;;
    *) echo Please enter only y or n
  esac
done
echo You entered $CONFIRM - continue...

echo Remove unused stuff e.g. firefox, thunderbird, and rare fonts
# samba should be removed from Mint 18 beta - causes problems.
apt-get -y --purge autoremove samba
apt-get -y --purge autoremove firefox  firefox-locale-en
apt-get -y --purge autoremove thunderbird  thunderbird-gnome-support 
apt-get -y --purge autoremove fonts-beng fonts-beng-extra fonts-deva fonts-droid fonts-gubbi fonts-gujr fonts-gujr-extra fonts-guru fonts-guru-extra fonts-kacst fonts-kacst-one fonts-kalapi fonts-khmeros-core fonts-knda fonts-lao fonts-lklug-sinhala fonts-lohit-beng-assamese fonts-lohit-beng-bengali fonts-lohit-deva fonts-lohit-gujr fonts-lohit-guru fonts-lohit-knda fonts-lohit-mlym fonts-lohit-orya fonts-lohit-taml fonts-lohit-taml-classical fonts-lohit-telu fonts-nakula fonts-nanum fonts-navilu fonts-noto-unhinted fonts-orya-extra fonts-pagul fonts-sahadeva fonts-samyak-deva fonts-samyak-gujr fonts-samyak-mlym fonts-samyak-taml fonts-sarai fonts-smc fonts-sil-abyssinica fonts-sil-padauk fonts-takao-pgothic fonts-taml fonts-telu fonts-telu-extra fonts-thai-tlwg fonts-tibetan-machine fonts-tlwg-garuda fonts-tlwg-garuda-ttf fonts-tlwg-kinnari fonts-tlwg-kinnari-ttf fonts-tlwg-laksaman fonts-tlwg-laksaman-ttf fonts-tlwg-loma fonts-tlwg-loma-ttf fonts-tlwg-mono fonts-tlwg-mono-ttf fonts-tlwg-norasi fonts-tlwg-norasi-ttf fonts-tlwg-purisa fonts-tlwg-purisa-ttf fonts-tlwg-sawasdee fonts-tlwg-sawasdee-ttf fonts-tlwg-typewriter fonts-tlwg-typewriter-ttf fonts-tlwg-typist fonts-tlwg-typist-ttf fonts-tlwg-typo fonts-tlwg-typo-ttf fonts-tlwg-umpush fonts-tlwg-umpush-ttf fonts-tlwg-waree fonts-tlwg-waree-ttf fonts-wqy-microhei fonts-wqy-zenhei ttf-indic-fonts-core ttf-punjabi-fonts ttf-wqy-microhei 

# delete these files so that recommends are installed by default
rm -v /etc/apt/apt.conf.d/00recommends /etc/apt/apt.conf.d/99synaptic

# enable the Update for inxi
sed -i 's/^B_ALLOW_UPDATE=false/B_ALLOW_UPDATE=true/' /etc/inxi.conf
inxi -U

# replace /etc/default/grub and /etc/grub.d/40_custom and /etc/grub.d/06_mint_theme with my customized versions
cp grub /etc/default/
cp 40_custom /etc/grub.d/
cp 06_mint_theme /etc/grub.d/
cp 161807-neblu.jpg /boot/grub/
cp dan /etc/sudoers.d/

# Reduce swappiness from 60 to 5
echo "vm.swappiness=5" | sudo tee -a /etc/sysctl.conf

ufw enable

# Fix the Power Management problem with my wireless card by changing wifi.powersave to disabled
sudo sed -i 's/wifi.powersave = 3/wifi.powersave = 2/' /etc/NetworkManager/conf.d/default-wifi-powersave-on.conf

echo Get rid of the annoying Warning No support - en_US.utf8
locale-gen --purge --no-archive

# Restore all repository keys - optional. Use only when cloning the same version !
# apt-key add ./repo.keys

# add ubuntuzilla ppa (Seamonkey) and MultiSystem ppa (additional-repositories.list)
cp ./apt/sources.list.d/additional-repositories.list /etc/apt/sources.list.d/

echo Install ubuntuzilla ppa key
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com C1289A29

echo Install MultiSystem ppa key
wget -q -O - http://liveusb.info/multisystem/depot/multisystem.asc | sudo apt-key add -

# add Google Chrome ppa
cp ./apt/sources.list.d/google-chrome.list /etc/apt/sources.list.d/
echo Install Google Chrome key
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - 

echo Copying all old .deb files
cp ./archives/*.deb /var/cache/apt/archives/

apt-get -y update

echo Install all the programs I use:
# avidemux avidemux-plugins-gtk flegita-gimp not available in Mint 18 repo 
# -r = Treat recommendations as dependencies
apt-get -y --show-progress install  acetoneiso album apport-gtk asunder bluefish boot-info-script clipit converseen cthumb dconf-tools dvdbackup filezilla fsarchiver fslint geany gimp glances glines gnome-brave-icon-theme gnome-color-chooser gnome-logs gnome-search-tool google-chrome-stable gparted gpick grml-rescueboot grml2usb grsync gsmartcontrol gtkhash gwenrename hardinfo htop imagemagick-doc inkscape leafpad medit meld mint-meta-codecs multisystem nemo-image-converter openshot pinta pithos pmount preload puddletag roxterm seamonkey-mozilla-build shutter smartmontools smplayer smtube swapspace vlc xsane

# alternative program installation commands:
# apt-get -y install $(cat installed-software.list | awk '{print $1}')
# The apt-get command works great. Better than dpkg/dselect.
# Enter the next 4 commands to use the dpkg/dselect method.
# apt-get install dselect
# dselect update
# dpkg --set-selections < installed-software.list
# apt-get dselect-upgrade -y

# clean out unused .deb files
aptitude autoclean

echo Restoring personal configuration 
cp -a .avidemux $HOME/
cp -a .gconf $HOME/
cp -a  autostart $HOME/.config/
cp -a  Pinta $HOME/.config/
cp -a  puddletag $HOME/.config/
cp -a  roxterm.sourceforge.net $HOME/.config/
cp -a  smplayer $HOME/.config/
cp -a  vlc $HOME/.config/
cp -a  clipit $HOME/.config/
cp -a .filezilla $HOME/
cp -a  geany $HOME/.config/
cp -a .grsync $HOME/
cp -a .icons $HOME/
cp -a .local $HOME/
cp -a .multisystem $HOME/
cp -a .openshot $HOME/
cp -a .themes $HOME/
cp -a .wallpapers $HOME/
cp -a  google-chrome $HOME/.config/
cp -a  clock@cinnamon.org $HOME/.cinnamon/configs/
cp -a  seamonkey $HOME/.mozilla/
cp -a .asunder* $HOME/
cp -a .bash_history $HOME/
cp -a .gimp-2.8 $HOME/
cp -a .gnupg $HOME/
# .bashrc contains my custom aliases
cp -a .bashrc $HOME/
cp -a .face $HOME/
cp -a bin $HOME/
cp -a Templates/* $HOME/Templates/
cp -a .SamsungPrinter $HOME/

echo Restoring dconf settings
# "Perhaps first do a "dconf reset -f /org/cinnamon/" or "dconf reset -f /org/nemo/" 
# to reset all values to their default, before you load the customized values"
# - was not necessary for me on a fresh install of Mint 17.3 Cinnamon 
# might be necessary on a cloned OS
# This worked beautifully to restore a boatload of configuration!
dconf load /org/cinnamon/ < dconf.org.cinnamon
echo sleeping... waiting on dconf.org.cinnamon to complete...
sleep 5
dconf load /org/nemo/ < dconf.org.nemo

# Turn on the firewall
ufw enable

# Unhide the Startup Applications
sed -i 's/NoDisplay=true/NoDisplay=false/g' /etc/xdg/autostart/*.desktop

# make symlinks to my themes
ln -s $HOME/.themes/Dans_BurntOrangeLonghorn /usr/share/themes/Dans_BurntOrangeLonghorn
ln -s $HOME/.themes/Dans_MintyGreen-V3 /usr/share/themes/Dans_MintyGreen-V3
ln -s $HOME/.themes/Dans_RainyDayBlues /usr/share/themes/Dans_RainyDayBlues
ln -s $HOME/.themes/Dans_AutumnWoods /usr/share/themes/Dans_AutumnWoods

# create a mount point for my data partition:
mkdir $HOME/DATA
chown $USER:$USER $HOME/DATA
# add data partition to fstab
echo "# mount sda7 on /home/dan/DATA" | sudo tee -a /etc/fstab
echo "UUID=8f13cffd-fb93-4f54-92f6-9eec1f97cbd1   /home/dan/DATA   ext4   defaults,noatime   0   2" | sudo tee -a /etc/fstab
echo "# force temporary files to be stored in ram instead of on disk" | sudo tee -a /etc/fstab
echo "none /tmp     tmpfs nodev,nosuid,mode=1777 0 0" | sudo tee -a /etc/fstab
mount -a

echo Install Samsung printer and scanner drivers...
sleep 3
cd $HOME/bin/SamsungPrinter/uld/
./install.sh
cd $HOME

# install the pirate icon for xkill
rm /usr/share/icons/DMZ-White/cursors/pirate
cp bin/pirate.png /usr/share/icons/DMZ-White/cursors/

echo DONE !
echo Do you want to reboot now?
while true
do
  echo -n "Please confirm y(es) or n(o):"
  read CONFIRM
  case $CONFIRM in
    y|Y|YES|yes|Yes) break ;;
    n|N|no|NO|No)
      echo Aborting - you entered $CONFIRM
      exit
      ;;
    *) echo Please enter only y or n
  esac
done
echo You entered $CONFIRM - rebooting...
shutdown -r now
Mint 18.2 Cinnamon, Quad core AMD A8-3870 with Radeon HD Graphics 6550D, 8GB DDR3, Ralink RT2561/RT61 802.11g PCI
Linux Linx 2018
User avatar
xenopeek
Level 25
Level 25
Posts: 29507
Joined: Wed Jul 06, 2011 3:58 am

Re: How to implement an "Are you root?" test in a shell script

Post by xenopeek »

I'd normally use the $EUID test as I do most of my scripting with bash. $EUID would be set to the user you changed to but mind that bash drops to the real user and doesn't run scripts with as the effective user. Also the setuid permission on scripts isn't honored on Linux I believe. So you will never see a difference between $EUID and $UID in bash scripts—both will have the value of $UID (even when you setuid bash itself).

I had a good head scratcher on this BTW, as I was testing in my home directory a bit and had forgotten I had set the mount options for that to nosuid :lol: Security first, but don't forget you implemented it :roll:

A test that can be adopted to work with all other shells I think is to use id -u and compare the result with 0 (zero). So for bash:

Code: Select all

if [[ $(id -u) -ne 0 ]]; then
    # your code for what to do when not run as root
fi
Image
rene
Level 20
Level 20
Posts: 12240
Joined: Sun Mar 27, 2016 6:58 pm

Re: How to implement an "Are you root?" test in a shell script

Post by rene »

My bunch of backup scripts /home/rene/bin/backup-[something] all start with

Code: Select all

#!/bin/sh
[ $(id -u) -eq 0 ] || exec sudo "$0"
which is to say they relaunch themselves when not run as root. Combine with a file /etc/sudoers.d/backup consisting of, say,

Code: Select all

Cmnd_Alias BACKUP = /home/rene/bin/backup-*

rene ALL=(ALL) NOPASSWD: BACKUP
and you have a fully automated solution.

(be sure to chmod 440 /etc/sudoers.d/backup as usual for sudoers.d files).
User avatar
xenopeek
Level 25
Level 25
Posts: 29507
Joined: Wed Jul 06, 2011 3:58 am

Re: How to implement an "Are you root?" test in a shell script

Post by xenopeek »

That is a nice solution. You may want to replace the second line with following to relaunch the script with all arguments passed to it (your version doesn't pass arguments):

Code: Select all

#!/bin/sh
[ $(id -u) -eq 0 ] || exec sudo "$0 $*"
Image
rene
Level 20
Level 20
Posts: 12240
Joined: Sun Mar 27, 2016 6:58 pm

Re: How to implement an "Are you root?" test in a shell script

Post by rene »

Indeed. My own scripts don't take arguments but generally, indeed. And now that I posted the above sudo automation as well, I should remark/warn that with that specific /etc/sudoers.d/backup file someone able to place an executable file called "backup-foo" inside of ~/bin in your home directory gains root privileges. Not necessarily an issue, but should still note it.
lmuserx4849

Re: How to implement an "Are you root?" test in a shell script

Post by lmuserx4849 »

This is the test [[ ${EUID} == 0 ]] in /etc/bashrc. /etc/profile shows [ "`id -u`" -eq 0 ].

I took a different tack --- I wrote doc with asciidoc ;-) I never change an install file (or directory if need be) without backing it up first; usually adding a suffix .install or .%Y%m%d%S. I can do a find for the suffix to see what files have been changed and a diff to see what in the file changed. I really enjoy reading configuration files. There is so much doc in them. Even if there is a gui, I still try to follow this procedure. A long time ago, I used something called webmin for configuration. It has automation.

There are certain user files I know I want so I list them in an array and copy... something like:

Code: Select all

declare -r configFiles=(
  ".bashrc"
  "other files"
)

get_config_files() {  rsync -avxzR "${userathost}""${configFiles[@]}"  "${HOME}/${configFilesDir}/";  return $? }
Arikania

Re: How to implement an "Are you root?" test in a shell script

Post by Arikania »

It is useful only rarely, but you could in some instances decide to ignore being or not being root, until the practice at run-time proves it to be relevant and not the case. This could be a strategy for programs which has modes that do and modes that do not need to be run as root.

But indeed, typically it is a more elegant solution to first have your program check whether root mode is necessary and if the user validates, before commencing at all. Especially if the program has modes which are definitely not to be run as root, like internet games and programs in the "explode_my.desktop" category.
jharris1993
Level 3
Level 3
Posts: 188
Joined: Mon Nov 05, 2012 9:43 pm
Location: Worcester Ma. (USA) when I'm not in Moscow Russia
Contact:

Re: How to implement an "Are you root?" test in a shell script

Post by jharris1993 »

xenopeek wrote:You may want to replace the second line with following to relaunch the script with all arguments passed to it [. . .]:

Code: Select all

#!/bin/sh
[ $(id -u) -eq 0 ] || exec sudo "$0 $*"
Cute! I like it ! Great user experience handling the error - doesn't get pissy but just requests the process elevation needed. I'm going to have to put this one in my Linux "Book of Magic Spells" where I keep cute tricks like this.

Question: What happens to the script that executes the "exec" command? Does the calling script die? Is it like a subroutine call? (If not, can you do something like a subroutine call within a script?)

Jim (JR)
Jim "JR"

Some see things as they are, and ask "Why?"
I dream things that never were, and ask "Why Not".

Robert F. Kennedy

“Impossible” is only found in the dictionary of a fool.
Old Chinese Proverb
User avatar
xenopeek
Level 25
Level 25
Posts: 29507
Joined: Wed Jul 06, 2011 3:58 am

Re: How to implement an "Are you root?" test in a shell script

Post by xenopeek »

The calling script dies after exec. FYI, you can get help for bash builtin commands with the command help. As in, help exec would give you info on the command:

Code: Select all

exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
    Replace the shell with the given command.
    
    Execute COMMAND, replacing this shell with the specified program.
    ARGUMENTS become the arguments to COMMAND.  If COMMAND is not specified,
    any redirections take effect in the current shell.
    
    Options:
      -a name	pass NAME as the zeroth argument to COMMAND
      -c	execute COMMAND with an empty environment
      -l	place a dash in the zeroth argument to COMMAND
    
    If the command cannot be executed, a non-interactive shell exits, unless
    the shell option `execfail' is set.
    
    Exit Status:
    Returns success unless COMMAND is not found or a redirection error occurs.
Image
rene
Level 20
Level 20
Posts: 12240
Joined: Sun Mar 27, 2016 6:58 pm

Re: How to implement an "Are you root?" test in a shell script

Post by rene »

And as to your second question; calling a script without exec would indeed be like a subroutine call, in the sense that execution continues after it returns. Note that this would in this specific case of callee being the same thing as caller mean that the (remainder of the) script would be run once more, but this time without elevated privileges.

But calling an external script would not be generally referred to in terms of being a subroutine call, seeing as how (ba)sh also provides for actual subroutines ("functions"). I.e.,

Code: Select all

#!/bin/sh

foo () {
  echo Foo... $1
}

foo bar
foo zle
So, yes, certainly you can. Either through shell functions as above, or by proclaiming an external script to be a subroutine.
jharris1993
Level 3
Level 3
Posts: 188
Joined: Mon Nov 05, 2012 9:43 pm
Location: Worcester Ma. (USA) when I'm not in Moscow Russia
Contact:

Re: How to implement an "Are you root?" test in a shell script

Post by jharris1993 »

@rene

Thanks!

I've been trying to figure this stuff out for ages as the usual literature assumes that you already know the stuff.

Jim (JR)
Jim "JR"

Some see things as they are, and ask "Why?"
I dream things that never were, and ask "Why Not".

Robert F. Kennedy

“Impossible” is only found in the dictionary of a fool.
Old Chinese Proverb
Locked

Return to “Scripts & Bash”