Running makefile command as another user - linux

I have two scripts, owned by root.
#!/bin/sh
#script1.sh
echo "all: first" > my_makefile
echo >> my_makefile
echo "first: " >> my_makefile
echo "\ttouch file.txt" >> my_makefile
#!/bin/sh
#script2.sh
while true
do
make -f my_makefile
sleep 10
done
script2.sh is called as "sudo sh script.sh" and continually runs make on my_makefile. script1.sh is called by individual users to alter the makefile.
How can I run the makefile command so that the file.txt is owned by the user, rather than root?

#!/bin/sh
#script1.sh
...
echo "\tchown "`logname`" file.txt" >> my_makefile

Sorry, I wasn't using sudo correctly. I just needed to replace the last line of script2.sh with:
echo "sudo su -m -l `whoami` -c \"touch file.txt\"" >> my_makefile

Related

Limited a user with creating rbash, exporting the path in .bashrc but /bin/ls still works

I tried limiting ls command to a specific user. It works, but when I execute /bin/ls, it executes successfully again, how to restrict here.
useradd -m $username -s /bin/rbash
echo "$username:$password" | chpasswd
mkdir /home/$username/bin
chmod 755 /home/$username/bin
echo "PATH=$HOME/bin" >> /home/$username/.bashrc
echo "export PATH" >> /home/$username/.bashrc
ln -s /bin/ls /home/$username/bin/

Changing msg_max size on Linux [duplicate]

This question already has answers here:
How do I use sudo to redirect output to a location I don't have permission to write to? [closed]
(15 answers)
Closed 1 year ago.
This is a pretty simple question, at least it seems like it should be, about sudo permissions in Linux.
There are a lot of times when I just want to append something to /etc/hosts or a similar file but end up not being able to because both > and >> are not allowed, even with root.
Is there someway to make this work without having to su or sudo su into root?
Use tee --append or tee -a.
echo 'deb blah ... blah' | sudo tee -a /etc/apt/sources.list
Make sure to avoid quotes inside quotes.
To avoid printing data back to the console, redirect the output to /dev/null.
echo 'deb blah ... blah' | sudo tee -a /etc/apt/sources.list > /dev/null
Remember about the (-a/--append) flag!
Just tee works like > and will overwrite your file. tee -a works like >> and will write at the end of the file.
The problem is that the shell does output redirection, not sudo or echo, so this is being done as your regular user.
Try the following code snippet:
sudo sh -c "echo 'something' >> /etc/privilegedfile"
The issue is that it's your shell that handles redirection; it's trying to open the file with your permissions not those of the process you're running under sudo.
Use something like this, perhaps:
sudo sh -c "echo 'something' >> /etc/privilegedFile"
sudo sh -c "echo 127.0.0.1 localhost >> /etc/hosts"
Doing
sudo sh -c "echo >> somefile"
should work. The problem is that > and >> are handled by your shell, not by the "sudoed" command, so the permissions are your ones, not the ones of the user you are "sudoing" into.
I would note, for the curious, that you can also quote a heredoc (for large blocks):
sudo bash -c "cat <<EOIPFW >> /etc/ipfw.conf
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<plist version=\"1.0\">
<dict>
<key>Label</key>
<string>com.company.ipfw</string>
<key>Program</key>
<string>/sbin/ipfw</string>
<key>ProgramArguments</key>
<array>
<string>/sbin/ipfw</string>
<string>-q</string>
<string>/etc/ipfw.conf</string>
</array>
<key>RunAtLoad</key>
<true></true>
</dict>
</plist>
EOIPFW"
In bash you can use tee in combination with > /dev/null to keep stdout clean.
echo "# comment" | sudo tee -a /etc/hosts > /dev/null
Some user not know solution when using multiples lines.
sudo tee -a /path/file/to/create_with_text > /dev/null <<EOT
line 1
line 2
line 3
EOT
Using Yoo's answer, put this in your ~/.bashrc:
sudoe() {
[[ "$#" -ne 2 ]] && echo "Usage: sudoe <text> <file>" && return 1
echo "$1" | sudo tee --append "$2" > /dev/null
}
Now you can run sudoe 'deb blah # blah' /etc/apt/sources.list
Edit:
A more complete version which allows you to pipe input in or redirect from a file and includes a -a switch to turn off appending (which is on by default):
sudoe() {
if ([[ "$1" == "-a" ]] || [[ "$1" == "--no-append" ]]); then
shift &>/dev/null || local failed=1
else
local append="--append"
fi
while [[ $failed -ne 1 ]]; do
if [[ -t 0 ]]; then
text="$1"; shift &>/dev/null || break
else
text="$(cat <&0)"
fi
[[ -z "$1" ]] && break
echo "$text" | sudo tee $append "$1" >/dev/null; return $?
done
echo "Usage: $0 [-a|--no-append] [text] <file>"; return 1
}
You can also use sponge from the moreutils package and not need to redirect the output (i.e., no tee noise to hide):
echo 'Add this line' | sudo sponge -a privfile
By using sed -i with $ a , you can append text, containing both variables and special characters, after the last line.
For example, adding $NEW_HOST with $NEW_IP to /etc/hosts:
sudo sed -i "\$ a $NEW_IP\t\t$NEW_HOST.domain.local\t$NEW_HOST" /etc/hosts
sed options explained:
-i for in-place
$ for last line
a for append
echo 'Hello World' | (sudo tee -a /etc/apt/sources.list)
How about:
echo text | sudo dd status=none of=privilegedfile
I want to change /proc/sys/net/ipv4/tcp_rmem.
I did:
sudo dd status=none of=/proc/sys/net/ipv4/tcp_rmem <<<"4096 131072 1024000"
eliminates the echo with a single line document
This worked for me:
original command
echo "export CATALINA_HOME="/opt/tomcat9"" >> /etc/environment
Working command
echo "export CATALINA_HOME="/opt/tomcat9"" |sudo tee /etc/environment
Can you change the ownership of the file then change it back after using cat >> to append?
sudo chown youruser /etc/hosts
sudo cat /downloaded/hostsadditions >> /etc/hosts
sudo chown root /etc/hosts
Something like this work for you?

How to log non-interactive bash command sent through ssh

I'm sending a command through ssh:
ssh server.org 'bash -s' << EOF
ls -al
whoami
uptime
EOF
How to log it in the system (remote server)? I'd like to log those commands in some file (.bash_history or /tmp/log).
I've tried to add the line below to sshd_config:
ForceCommand if [[ -z $SSH_ORIGINAL_COMMAND ]]; then bash; else echo "$SSH_ORIGINAL_COMMAND" >> .bash_history; bash -c "$SSH_ORIGINAL_COMMAND"; fi
But it logs "bash -s" only.
I'll appreciate any help.
When bash shell exits, bash reads and executes commands from the ~/.bash_logout file. Probably you can run the history command at the end in the .bash_logout(of the server) and save it to some location.
If it suffices to work with the given command, we can put the necessary additions to enable and log command history at the beginning and end, e. g.
ssh server.org bash <<EOF
set -o history
ls -al
whoami
uptime
history|sed 's/ *[0-9]* *//' >>~/.bash_history
EOF
Or we could put them into the awfully long ForceCommand line:
… if [[ "$SSH_ORIGINAL_COMMAND" == bash* ]]; then echo "set -o history"; cat; echo "history|sed 's/ *[0-9]* *//' >>~/.bash_history"; else cat; fi | bash -c "$SSH_ORIGINAL_COMMAND"; fi

Close gnome-terminal with specific title from another script/shell command

I need to close a specific gnome-terminal window having a unique name from any other bash/shell script.
Eg:
$] gnome-terminal --title "myWindow123" -x "watch ls /tmp"
...
...
gnome-terminal opened in the name "myWindow123"
All I need is to kill that terminal from my script. Is there expect kind of script support in bash also?
As a contestant for the ugliest hack of the day:
sh$ TERMPID=$(ps -ef |
grep gnome-terminal | grep myWindow123 |
head -1 | awk '{ print $2 }')
sh$ kill $TERMPID
A probably better alternative would be to record the PID of the terminal at launch time, and then kill by that pid:
sh$ gnome-terminal --title "myWindow123" -x "watch ls /tmp"
sh$ echo $! > /path/to/my.term.pid
...
...
# Later, in a terminal far, far away
sh$ kill `cat /path/to/my.term.pid`
In the script that starts the terminal:
#!/bin/bash
gnome-terminal --title "myWindow123" --disable-factory -x watch ls /tmp &
echo ${!} > /var/tmp/myWindow123.pid
In the script that shall slay the terminal:
#!/bin/bash
if [ -f /var/tmp/myWindow123.pid ]; then
kill $(cat /var/tmp/myWindow123.pid && rm /var/tmp/myWindow123.pid)
fi
It's a bit of an ugly hack, but you can create a wrapper script that takes a nonce as an argument, and then kill that.
cat > ~/wrapper.sh < 'EOF'
#!/bin/sh
#Throw away the nonce, and then run the command given
shift
"$#"
EOF
chmod +x ~/wrapper.sh
#Make a random string, so we can kill it later
nonce=`tr -dc '0-9A-Za-z' < /dev/urandom | head -n 10`
gnome-terminal -- ~/wrapper.sh "$nonce" watch ls /tmp
#...
#...
#...
#Kill any command with our nonce as one of its arguments
pkill -f "$nonce"

Bash script output not going to stdout

I have a build process, kicked off by Make, that executes a lot of child scripts.
A couple of these child scripts require root privileges, so instead of running everything as root, or everything as sudo, I'm trying to only execute the scripts that need to be as root, as root.
I'm accomplishing this like so:
execute_as_user() {
su "$1" -s /bin/bash -c "$2;exit \$?"
}
Arg $1 is the user to run the script as, arg $2 is the script.
Arg $1 is either root (gotten with: $(whoami) since everything is under sudo), or the current user's account (gotten with: $(logname))
The entire build is kicked off as:
sudo make all
Sample from the Makefile:
LOG="runtime.log"
ROTATE_LOG:=$(shell bash ./scripts/utils/rotate_log.sh)
system:
/bin/bash -c "time ./scripts/system.sh 2>&1 | tee ${LOG}"
My problem is... none of the child scripts are printing output to stdout. I believe it to be some sort of issue with an almost recursive call of su root... but I'm unsure. From my understanding, these scripts should already be outputting to stdout, so perhaps I'm mistaken where the output is going?
To be clear, I'm seeing no output in either the logfile nor displaying to the terminal (stdout).
Updating for clarity:
Previously, I just ran all the scripts either with sudo or just as the logged in user... which with my makefile above, would print to the terminal (stdout) and logfile. Adding the execute_as_user() function is where the issue cropped up. The scripts execute and build the project... just no display "that it's working" and no logs.
UPDATE
Here is some snippets:
system.sh snippet:
execute_script() {
echo "Executing as user $3: $2"
RETURN=$(execute_as_user $3 ${SYSTEM_SCRIPTS}/$2)
if [ ${RETURN} -ne ${OK} ]
then
error $1 $2 ${RETURN}
fi
}
build_package() {
local RETURN=0
case "$1" in
system)
declare -a scripts=(\
"rootfs.sh" \
"base_files.sh" \
"busybox.sh" \
"iana-etc.sh" \
"kernel.sh" \
"firmware.sh" \
"bootscripts.sh" \
"network.sh" \
"dropbear.sh" \
"wireless_tools.sh" \
"e2fsprogs.sh" \
"shared_libs.sh"
)
for SCRIPT_NAME in "${scripts[#]}"; do
execute_script $1 ${SCRIPT_NAME} $(logname)
echo ""
echo -n "${SCRIPT_NAME}"
show_status ${OK}
echo ""
done
# finalize base system
echo ""
echo "Finalizing base system"
execute_script $1 "finalize.sh" $(whoami)
echo ""
echo -n "finalize.sh"
show_status ${OK}
echo ""
# package into tarball
echo ""
echo "Packing base system"
execute_script $1 "archive.sh" $(whoami)
echo ""
echo -n "archive.sh"
show_status ${OK}
echo ""
echo ""
echo -n "Build System: "
show_status ${OK}
;;
*)
echo "$1 is not supported!"
exit 1
esac
}
sample child script executed by system.sh
cd ${CLFS_SOURCES}/
tar -xvjf ${PKG_NAME}-${PKG_VERSION}.tar.bz2
cd ${CLFS_SOURCES}/${PKG_NAME}-${PKG_VERSION}/
make distclean
RESPONSE=$?
if [ ${RESPONSE} -ne 0 ]
then
pkg_error ${RESPONSE}
exit ${RESPONSE}
fi
ARCH="${CLFS_ARCH}" make defconfig
RESPONSE=$?
if [ ${RESPONSE} -ne 0 ]
then
pkg_error ${RESPONSE}
exit ${RESPONSE}
fi
# fixup some bugs with musl-libc
sed -i 's/\(CONFIG_\)\(.*\)\(INETD\)\(.*\)=y/# \1\2\3\4 is not set/g' .config
sed -i 's/\(CONFIG_IFPLUGD\)=y/# \1 is not set/' .config
etc...
Here's the entire system.sh script:
https://github.com/SnakeDoc/LiLi/blob/master/scripts/system.sh
(i know the project is messy... it's a learn-as-you-go style project)
Previously, I just ran all the scripts either with sudo or just as the
logged in user... which with my makefile above, would print to the
terminal (stdout) and logfile. Adding the execute_as_user() function
is where the issue cropped up. The scripts execute and build the
project... just no display "that it's working" and no logs.
Just a guess, but you're probably not calling your function or not calling it properly:
execute_as_user() {
su "$1" -s /bin/bash -c "$2;exit \$?"
}
execute_as_user "$#"
I also noticed that you're not passing any argument to the script at all. Is this meant?
./scripts/system.sh ???

Resources