Saturday, May 18, 2024
 Popular · Latest · Hot · Upcoming
-1
rated 0 times [  -1] [ 0]  / answers: 1 / hits: 19643  / 1 Year ago, mon, february 6, 2023, 1:52:11

How to elevate privileges to root in bash? And then how to return back to exactly the previous state? My question is both about elevating/decreasing privileges and possible troubles with some apps, especially GUI apps (and an “environment”).



Say, some apps keep a separate profile for each user and root. GUI & profiles may be not the only problem with an “environment” if I run an app as root, regardless of whether this is their or OS’s bug or a feature.



Say, I need to run a script as root or already run a script as root (like in rc.local), so you might need to decrease the privileges or "completely" switch back to the normal user from there (su normaluser does not always work). To run initially a script with sudo -H and then to switch to another user? This does not always work as needed especially with GUI apps. I believe the trouble is with an "environment", and DISPLAY=:0 ... or DISPLAY=:0 gtk-launch ... (gtk-launch is likely bugged) may be yet not helpful.



Say, I have gedit with an opened document. If I run as just a normal user gedit /doc2, it opens with menu visible and in the already existing window in another tab. If I run it as root, it opens up in a separate window and without visible menu. If I run a script through sudo -H or su and try to run gedit /doc2 there as that normal user (again with sudo (-H) or su), then it works as if I did that as root, not that normal user. I tried also sudo options -l, -s, -i. With other GUI apps that caused far more serious troubles. Some GUI apps have different GUI or don’t run at all as a result.
Sometimes runuser was helpful for me but not always. And heredoc format (sudo -H /bin/bash <<EOF <lines with commands> EOF) does not work as expected.



It is how many troubles this makes. For more than 1 year I could not find a good universal solution. So is there anything for elevation of privileges and returning back? Or other good workarounds?



And a full example just in case (run as sudo ./script.sh or with -H):



cd /somedir
some_commands # using the current directory, root privileges and setting some variables, and writing to somefile (better as normal user)
sudo -u normaluser /bin/bash -c 'gedit --encoding someencoding /somefile'`


If I run the following bash script as just ./script.sh



gedit --encoding someencoding /somefile


then gedit works as it should.



Just in case: it is about Ubunu 16.04 xenial, bash version 4.3.48.



Update:



I know I could run commands like



sudo sh -c ‘command1 $somevariable; command2’


or (I've found out it can be several lines)



sudo sh -c ‘command1 $somevariable command2’


or maybe something similar with bash. That might not be an option for a large set of commands and does not solve all the problems. And I absolutely don’t need to enter commands interactively. See also my answer.



P.S. I think Linux should user-friendly and easy to use.


More From » bash

 Answers
2

My answer. Yet a solution of how to just elevate and decrease privileges (actually, conceptually without even wrapping, existing separately) or to fully switch to root and back is required.



Basing on suggestions of me, LeonidMew and WinEunuuchs2Unix, here is the workaround. The -H option is usually a good choice so I include it.



There are two workarounds (bash can be replaced with sh):



1) sudo -H /bin/bash -c ‘commands’ and



2) sudo -H /bin/bash -c “commands” (as well as the heredoc format, sudo -H /bin/bash <<EOF <lines with commands> EOF).



1) Variables from outside are not visible inside automatically. They would have to be moved inside, be double-defined or be passed as arguments. I could not make or pass a short (re)declaration of an external function like $(declare -f functionname) inside (maybe it is yet possible), but it worked if I just moved it inside.



2) Only copies of variables from outside are passed inside. You will have to escape with constructs $(...), $PWD or other locally defined variables, AND commenting with # may not work (as with the #$(declare -f ...)). Arguments like $1 are the ones of the whole script and cannot be passed inside as local variables. Externally defined functions are not visible inside but can be redeclared inside like $(declare -f functionname).



In the both cases you can get output through files or a fast string-output from stdout (or several space-separated variables) through the wrapping res=$(...). You can see an example here: https://stackoverflow.com/a/23567255 . Though after the wrapping all EOLs are converted into spaces. Maybe export, designed to pass variables to subprocesses, will help to avoid that wrapping or the usage of files, but somehow it didn’t work for me.



The case 1) seems to be the best default choice and will most likely require less modifications of the existing code, contrary to the case 2) when a careful modification of the existing code will usually be required. Maybe you will find the both cases useful simultaneously.



This is my simple example:



tmpdir=/tmp/
tmpfile=/tmp/tmpfile
res=$(sudo -H bash -c 'tmpdir=$1; tmpfile=$2
echo "$tmpdir;"
cd $ tmpdir
echo $(pwd)
echo "A string from file" > $tmpfile
' - $tmpdir $tmpfile)
echo $res
arr=($res)
echo ${arr[0]} # Hellooo
echo ${arr[1]} # world;
echo ${arr

  • } # whole array
    echo ${#arr
  • [*]} # number of items
    n=0
    echo ${#arr[$n]} # length of the n-th element
    cat $tmpfile
    sudo sh -c 'rm -f $2' - - $tmpfile


    [#5638] Tuesday, February 7, 2023, 1 Year  [reply] [flag answer]
    Only authorized users can answer the question. Please sign in first, or register a free account.
    nquirewha

    Total Points: 256
    Total Questions: 109
    Total Answers: 122

    Location: Namibia
    Member since Mon, Feb 21, 2022
    2 Years ago
    ;