Bash

使用 EOF 訪問腳本中 sudo 子句中的變數

  • September 2, 2018

問題:

我需要在這裡有一個名為 $user 的變數:

chown $user:$user "$HOME"/.bashrc

但它無法從sudoand外部訪問它EOF

for user in "$@"
do
   if [ "$user" = root ]
   then
       continue
   fi
   sudo -i -u "$user" bash <<'EOF'
   sleep 5
   cp -f $CURRENTDIR/.bashrc "$HOME"/.bashrc
   chown $user:$user "$HOME"/.bashrc
   sleep 5
   chmod 644 "$HOME"/.bashrc
   sleep 5
   wget https://raw.github.com/trapd00r/LS_COLORS/master/LS_COLORS -O "$HOME"/.dircolors
   sleep 5
   echo 'eval $(dircolors -b $HOME/.dircolors)' >> "$HOME"/.bashrc
   . "$HOME"/.bashrc
EOF
done

問題:

如何在我的腳本中訪問 $user?

這是完整的腳本:

#!/bin/bash -x

SCRIPTNAME=`basename "$0"`

if [ "$#" -eq 0 ]
then
   echo "No arguments supplied"
   echo "Usage: $SCRIPTNAME user1name user2name\(optional\) user3name\(optional\)"
   sleep 10
   exit 27
fi

sleep 5
echo "Setting up server.........."
sleep 10

DIRBASHRCROOT="$HOME"/.bashrcroot
DIRBASHRC="$HOME"/.bashrc
#CURRENTDIR="./"
BASHRC=.bashrc
NANORC=.nanorc
BASHRCROOT=.bashrcroot
ROOT=root
USER1="$1"
USER2="$2"
USER3="$3"
USER_PROGRAMMER=""
SOURCE=sources.list
var=0
for i in "$@"
do
   if [ "$i" = root ]
   then
       break
   elif [ "$i" != root ]
   then
       var=`expr $var + 1`
       if [ $var -eq 3 ]
       then
           USER_PROGRAMMER=root
       fi
   fi
done
if [ $USER_PROGRAMMER != "" ]
then
   echo "$USER_PROGRAMMER is set and ready!"
fi
sleep 5
echo "Please select/provide the port-number for ssh in iptables:"
read port
PORT=$port
################# Make my variable global for all ########################3↓
echo "export CURRENTDIR=\"/tmp/svaka\"" >> /root/.bashrc
touch /etc/profile.d/bashProgrammer.sh
echo "export CURRENTDIR=\"/tmp/svaka\"" >> /etc/profile.d/bashProgrammer.sh
. /root/.bashrc
. /etc/profile
. /etc/profile.d/bashProgrammer.sh
################ Users and access settings #####################

checkIfUser()
{
   for name in "$@"
   do
       if id -u "$name" #>/dev/null 2>&1
       then
           echo "User: $name exists....setting up now\!"
           sleep 5
       else
           echo "User: "$name" does not exists....creating now\!"
           useradd -m -s /bin/bash "$name" #>/dev/null 2>&1
           sleep 5
       fi
   done
}
checkIfUser $1 $2 $3
################33 user passwords
userPass()
{
   for i in "$@"
   do
       if [ "$i" = root ]
       then
           continue
       fi
       if [[ $(passwd --status "$i" | awk '{print $2}') = NP ]]
       then
           echo "$i doesn't have a password."
           echo "Changing password for $i:"
           echo $i:$i"YOURSTRONGPASSWORDHERE12345Áá" | chpasswd
           if [ "$?" = 0 ]
               then
               echo "Password for user $i changed successfully"
               sleep 5
           fi
       fi
   done
}
userPass $1 $2 $3
################################################ setting up iptables ####################3

cat << EOT >> /etc/iptables.test.rules
*filter

IPTABLES CODE HERE

COMMIT
EOT
sleep 5
iptables-restore < /etc/iptables.test.rules
sleep 5
iptables-save > /etc/iptables.up.rules
sleep 3
printf "#!/bin/bash\n/sbin/iptables-restore < /etc/iptables.up.rules" > /etc/network/if-pre-up.d/iptables
chmod +x /etc/network/if-pre-up.d/iptables
sleep 6
###################################################33 sshd_config
cp -f "$CURRENTDIR/sshd_config" /etc/ssh/sshd_config
sed -i "s/Port 34504/Port $PORT/g" /etc/ssh/sshd_config
chmod 644 /etc/ssh/sshd_config
/etc/init.d/ssh restart
#################################################3333 Remove or comment out DVD/cd line from sources.list

sed -i '/deb cdrom:\[Debian GNU\/Linux/s/^/#/' /etc/apt/sources.list
####################################################33 update system
apt update && apt upgrade -y
##########################################3 Disable login www #########
passwd -l www-data
###############################################################
############################# check if programs installed and/or install
if [ ! -x /usr/bin/git ] || [ ! -x /usr/bin/wget ] || [ ! -x /usr/bin/curl ] || [ ! -x /usr/bin/gcc ] || [ ! -x /usr/bin/make ]
then
   echo "Some tools with which to work with data not found installing now......................"
   apt install -y git wget curl gcc make
fi

#####################################################3 update sources.list
cp -f $CURRENTDIR/$SOURCE /etc/apt/sources.list
chmod 644 /etc/apt/sources.list
wget http://www.deb-multimedia.org/pool/main/d/deb-multimedia-keyring/deb-multimedia-keyring_2016.8.1_all.deb
dpkg -i deb-multimedia-keyring_2016.8.1_all.deb
wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add -
apt update && apt upgrade -y
apt install -y vlc vlc-data browser-plugin-vlc mplayer youtube-dl libdvdcss2 libdvdnav4 libdvdread4 smplayer mencoder
sleep 5
apt update && apt upgrade -y
sleep 5
#################################### firmware
apt install -y firmware-linux-nonfree firmware-linux
sleep 5
################ NANO SYNTAX-HIGHLIGHTING #####################3
if [ ! -d "$CURRENTDIR/nanorc"  ]
then
   if [ "$UID" != 0 ]
   then
       sudo -u "$ROOT" bash <<'EOF'
       sleep 5
       git clone https://github.com/nanorc/nanorc.git
       sleep 5
       cd nanorc
       make install-global
       sleep 5
       cp -f "$CURRENTDIR/.nanorc" /etc/nanorc
       chown root:root /etc/nanorc
       chmod 644 /etc/nanorc
       if [ "$?" = 0 ]
       then
           echo "Implementing a custom nanorc file succeeded\!"
       else
           echo "Nano setup DID NOT SUCCEED\!"
       fi
EOF
   else
       echo "Doing user: $USER....please, wait\!"
       git clone https://github.com/nanorc/nanorc.git
       sleep 5
       cd nanorc
       sleep 5
       make install-global
       sleep 5
       cp -f "$CURRENTDIR/$NANORC" /etc/nanorc
       chown root:root /etc/nanorc
       chmod 644 /etc/nanorc
       if [ "$?" = 0 ]
       then
           echo "Implementing a custom nanorc file succeeded\!"
       else
           echo "Nano setup DID NOT SUCCEED\!"
       fi
   fi
fi

echo "Finished setting up nano\!"
################ LS_COLORS SETTINGS #############################

if [ "$UID" != 0 ]
then
   echo "This program should be run as root, exiting\! now....."
   exit 1
  # sudo -i -u "$ROOT" bash <<'EOF'
  # BASHRCROOT=.bashrcroot
  # cp "$CURRENTDIR/$BASHRCROOT" "$HOME"/.bashrc
  # wget https://raw.github.com/trapd00r/LS_COLORS/master/LS_COLORS -O "$HOME"/.dircolors
  # echo 'eval $(dircolors -b $HOME/.dircolors)' >> "$HOME"/.bashrc
  # . "$HOME"/.bashrc
#EOF
else
   cp -f "$CURRENTDIR/$BASHRCROOT" "$HOME"/.bashrc
   chown root:root "$HOME"/.bashrc
   chmod 644 "$HOME"/.bashrc
   sleep 5
   wget https://raw.github.com/trapd00r/LS_COLORS/master/LS_COLORS -O "$HOME"/.dircolors
   sleep 5
   echo 'eval $(dircolors -b $HOME/.dircolors)' >> "$HOME"/.bashrc
   sleep 5
   . "$HOME"/.bashrc
fi
for user in "$@"
do
   if [ "$user" = root ]
   then
       continue
   fi
   sudo -i -u "$user" bash <<'EOF'
   sleep 5
   cp -f $CURRENTDIR/.bashrc "$HOME"/.bashrc
   chown $user:$user "$HOME"/.bashrc
   sleep 5
   chmod 644 "$HOME"/.bashrc
   sleep 5
   wget https://raw.github.com/trapd00r/LS_COLORS/master/LS_COLORS -O "$HOME"/.dircolors
   sleep 5
   echo 'eval $(dircolors -b $HOME/.dircolors)' >> "$HOME"/.bashrc
   . "$HOME"/.bashrc
EOF
done

echo "Finished setting up your system\!"
echo rm -rf /tmp/svaka

作為一般解決方案,您可以VAR=value在要執行的命令行中使用可能的多對將其他環境變數傳遞給 sudo 命令。

在這種特殊情況下,要傳遞$user變數,您可以使用:

sudo -i -u "$user" user="$user" bash <<'EOF'
...
chown $user:$user "$HOME"/.bashrc
...
EOF

(您也可以傳遞變數,例如$CURRENTDIR使用此方法而不是通過 rcfiles 推送它,因為您似乎是從腳本的其餘部分這樣做的。)

您需要一些特殊權限sudo才能設置其他環境變數。就像sudo 手冊頁的這一部分一樣:

如果在 sudoers 中設置了 setenv 選項,要執行的命令SETENV設置了標籤或匹配的命令是ALL,使用者可能會設置過度禁止的變數。有關詳細資訊,請參閱sudoers(5)

您還可以使用sudo -Es和保留來自呼叫使用者的環境。例如:

$ a=hi sudo -Es env | grep -i ^a=
a=hi

man sudo

-E, --preserve-env
            Indicates to the security policy that the user wishes to preserve their 
            existing environment variables.  The security policy may return an 
            error if the user does not have permission to preserve the environment.

-s, --shell
            Run the shell specified by the SHELL environment variable if it is set 
            or the shell specified by the invoking user's password database entry.  
            If a command is specified, it is passed to the shell for execution via 
            the shell's -c option.  If no command is specified, an interactive 
            shell is executed.

引用自:https://unix.stackexchange.com/questions/466312