10

I have a small bash script:

#!/bin/bash

touch dummy.txt

If I execute this script with sudo then it will create dummy.txt which will be root protected.

What I want to do is:

Regardless of whether this script is executed using sudo or a normal user, the file dummy.txt should not be root protected.

Zanna
  • 70,465
Anonymous
  • 239
  • 3
  • 5
  • 16
  • 4
    Whatever you mean by "root protected", you can use chown and chmod in your script to set ownership and permissions as desired. – fkraiem Nov 18 '16 at 09:33
  • 1
    It's not clear what you mean by "root protected". Do you mean that only the root user can read/write (eg file permissions are set to something like 700), or that the root user is the file owner? –  Nov 18 '16 at 15:48
  • 1
    @DoritoStyle sorry for the confusion. By root protected, I meant root user is the file owner. – Anonymous Nov 19 '16 at 10:56

3 Answers3

22

You could test if the script is being run via sudo using the EUID and SUDO_USER variables, and then execute touch as SUDO_USER if true - something like

#!/bin/bash

if [[ $EUID -eq 0 ]] && [[ -n $SUDO_USER ]]; then
  sudo -u "$SUDO_USER" touch dummy.txt
else
  touch dummy.txt
fi
steeldriver
  • 136,215
  • 21
  • 243
  • 336
  • 2
    Note that == used for string comparison. Since $EUID is supposed to return integer value, I'd recommend you use -ed comparison. Spaces are allowed in usernames , so probably quote the $SUDO_USER variable. Otherwise, good answer - this is something I personally would use. – Sergiy Kolodyazhnyy Nov 18 '16 at 08:09
  • @steeldriver this is what I was looking for. thanks!! – Anonymous Nov 18 '16 at 09:09
  • 1
    You could have the script re-run itself with sudo -u if it detects that it's running as root. The OP talked about having multiple commands in one script. But be careful to avoid an infinite loop on errors. – Peter Cordes Nov 18 '16 at 09:34
  • 1
    There's no word splitting within [[...]] so not strictly necessary to quote the variable within the if statement @Serg and I gues -ed was a typo for -eq – Arronical Nov 18 '16 at 09:39
  • @Arronical yes, that was typo for -eq. Didn't know [[ doesn't have word splitting. Thanks. Personally, I'd still quote for the sake of good scripting habits – Sergiy Kolodyazhnyy Nov 18 '16 at 10:06
  • @Serg I think the same, I always err on the side of more quotes rather than less, I don't actually know what those edge cases where you shouldn't quote are. I just asked a question on U&L to find out. – Arronical Nov 18 '16 at 10:08
  • @Arronical that question has been asked before, http://unix.stackexchange.com/q/68694/85039 Basically, if you want variable to be treated as single entity, use quotes. If you want contents to to be treated as several different words, don't use quotes. – Sergiy Kolodyazhnyy Nov 18 '16 at 10:13
  • @Serg thanks for the == catch, don't know why I didn't spot that (it was late here...) – steeldriver Nov 18 '16 at 12:57
  • You can do integer comparisons like this: (( EUID == 0 )) && [[ -n $SUDO_USER ]]. Note the optional omitting of the dollar sign and the use of == instead of the, IMO ugly, -eq. – Dennis Williamson Nov 18 '16 at 22:46
  • Minor nitpick: sudo su - doesn't leave SUDO_USER in the environment, so this would leave a root-protected file in that case. – muru Dec 08 '16 at 06:06
9

If your script is not meant to be run as root, the safest way to solve the problem is to abort the execution of the script at the very beginning:

if [ "$EUID" = 0 ]; then
   echo "This script must NOT be run as root" 
   exit 1
fi

Optionally, you can re-execute your script as a fallback user (e.g. sudo -u FALLBACK_USER "$0") instead of simply aborting.

Trying to fix the quirks of individual commands will make your script unnecessarily complex and hard to debug. Every time you modify it, you'll have to do all the testing twice (as a regular user, then as root), and fix all the root-related bugs that arise. It's not a future-proof solution, so to say.

luk3yx
  • 401
6

By default files created with root accound have permissions like so:

-rw-r--r-- 1 root root 0 11月 17 23:25 rootfile.txt

Here file belongs to root user and root group, and is readable and writable by root, but only readable by others.

Simplest approach would be just to chown the file back to the original user.

chown username:group_name dummy.txt

You can use $SUDO_USER variable that is accessible only when sudo is called, like so:

chown "$SUDO_USER":"$SUDO_USER" dummy.txt

If you're running script as regular user, the chown part is not needed at all, so you might want to consider using if-statement or && test to test for the case when script is run as root, and do something along these lines:

#!/bin/bash
touch dummy.txt
[ $UID -eq 0 ] && chown "$SUDO_USER":"$SUDO_USER" dummy.txt

The above is recommended approach. There are others, like using chmod to change read-write-execute permissions for users and group, but it's not recommended.

Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
  • thanks for your reply. But in Q I just explained simple scenario in real case original script will be creating many files. In linux can't we just simply ignore sudo ? – Anonymous Nov 18 '16 at 06:54
  • 1
    @Anonymous if you're executing the whole script with sudo , then no - you can't ignore it. Your option is either run script as regular user ( which I don't understand why you dont do , since you're simply creating a file for your user here ) or change file ownership like i show in my answer. – Sergiy Kolodyazhnyy Nov 18 '16 at 07:05
  • This is the most correct solution and it should not be that hard to scale up. – chicks Nov 18 '16 at 16:40