LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-22-2005, 12:55 PM   #1
rose_bud4201
Member
 
Registered: Aug 2002
Location: St Louis, MO
Distribution: Xubuntu, RHEL, Solaris 10
Posts: 929

Rep: Reputation: 30
A bash puzzle: queue up command for root to run?


There was no good title for this thread, so I'll apologize for that first.

This is in the context of writing a script which will take the last command I ran as myself (which involved doing something I forgot I didn't have permission to do, such as an ls on a protected directory), run it as root, and then drop me back down to my normal user shell - essentially, I want the 'sudamnit' command.

So what I'm trying to do is figure out how to do something like
Code:
#!/bin/bash

$command=`tail -n 1 ~/.bash_history`; #!! doesn't work here
`su - priviledged_user && $command && exit`
But doing that only su's me to priviledged_user, lets me do whatever I want, and then when I exit out it runs $command.

Anyone have any ideas, or can't this be done?
Thanks!
 
Old 08-22-2005, 04:36 PM   #2
stefanlasiewski
Member
 
Registered: Aug 2003
Location: Berkeley, California, USA
Distribution: Red Hat Enterprise Linux, Debian & Ubuntu
Posts: 92

Rep: Reputation: 16
`su - priviledged_user && $command && exit`

That will run each command one at a time. It will do:

'su - priviledged_user', then exit
$command, then exit
'exit' (which does nothing from a non-interactive shell on your system)

You need to pass the command directly to 'su', like this:

su - username -c $command

On some systems, you can eliminate the 'username' field and the '-c' field. Read the manpages.

Here's a simple example:


$ whoami
stefanl
$ su - whoami
Password:
root
$ whoami
stefanl
 
Old 08-22-2005, 08:17 PM   #3
puffinman
Member
 
Registered: Jan 2005
Location: Atlanta, GA
Distribution: Gentoo, Slackware
Posts: 217

Rep: Reputation: 31
Looking at .bash_history won't help for commands you just ran, because bash does not update this file until you exit the shell. Use the history command to access recently run commands.
 
Old 08-22-2005, 08:32 PM   #4
stefanlasiewski
Member
 
Registered: Aug 2003
Location: Berkeley, California, USA
Distribution: Red Hat Enterprise Linux, Debian & Ubuntu
Posts: 92

Rep: Reputation: 16
To take Puffinman's post and extend it-- you can refer to events in your history buffere with a '!' sign. To view the previous command, type '!-1' ("Refer to the current command line minus 1").

Using that trick, you can use the following to pass the previous command to 'su -':

Code:
$ whoami
stefanl
$ su - -c "!-1"
su - -c "whoami"
Password:
root
 
Old 08-23-2005, 01:15 AM   #5
puffinman
Member
 
Registered: Jan 2005
Location: Atlanta, GA
Distribution: Gentoo, Slackware
Posts: 217

Rep: Reputation: 31
And to further extend stefanlasiewski's (what a mouthful!) post, perhaps the easiest way to accomplish the task is to run sudo !-1. However, this is a little inconvenient to type, and when I try to make an alias for it, it no longer works. Perhaps it is necessary to resort to using the history library directly?
 
Old 08-23-2005, 07:40 AM   #6
rose_bud4201
Member
 
Registered: Aug 2002
Location: St Louis, MO
Distribution: Xubuntu, RHEL, Solaris 10
Posts: 929

Original Poster
Rep: Reputation: 30
That, and the problem for me is that this is a work server and I don't have sudo access to all the things that I need to run. I do, however, know the password for the more priviledged username which does have access...;-)

Hmmm...I think you're right about somehow involving the history library directly. I can run !-1 on the commandline, but I don't seem to be able to sript or alias it.

Last edited by rose_bud4201; 08-23-2005 at 08:20 AM.
 
Old 08-23-2005, 08:35 AM   #7
theYinYeti
Senior Member
 
Registered: Jul 2004
Location: France
Distribution: Arch Linux
Posts: 1,897

Rep: Reputation: 66
If an alias does not work, then maybe a function would. Here's a quick test I did (I don't have sudo nor su available):
Code:
function last() { echo $(fc -ln -1 -1); }
Replacing 'echo $(...)' with 'sudo "$(...)"' or 'su root -c "$(...)"' should work.

Yves.
 
Old 08-23-2005, 09:00 AM   #8
rose_bud4201
Member
 
Registered: Aug 2002
Location: St Louis, MO
Distribution: Xubuntu, RHEL, Solaris 10
Posts: 929

Original Poster
Rep: Reputation: 30
That does something very odd, and I'm not sure what it is...
It doesn't ask for a password, yet whatever command it's running isn't what it's supposed to.

[laura@cleopatra ~]$ fc -ln -1 -1
su

(that's correct)

But
[laura@cleopatra ~]$ tail /var/log/messages
tail: cannot open `/var/log/messages' for reading: Permission denied
[laura@cleopatra ~]$ sudamnit
laura pts/2 64.132.50.209 Tue Aug 23 08:50 still logged in
laura tty1 Tue Aug 23 07:38 still logged in
reboot system boot 2.4.26 Tue Aug 23 07:31 (01:22)
laura tty1 Mon Aug 22 07:17 - down (17:33)
reboot system boot 2.4.26 Mon Aug 22 07:13 (17:37)
laura tty1 Sun Aug 21 10:30 - down (12:21)
reboot system boot 2.4.26 Sun Aug 21 10:13 (12:38)
laura tty1 Sat Aug 20 17:40 - down (08:00)
reboot system boot 2.4.26 Sat Aug 20 17:40 (08:00)
laura tty1 Sat Aug 20 12:29 - down (05:10)
reboot system boot 2.4.26 Sat Aug 20 12:27 (05:12)
laura pts/0 64.132.50.209 Thu Aug 18 13:49 - 16:01 (02:11)
laura pts/0 64.132.50.209 Thu Aug 18 11:05 - 13:48 (02:43)
laura tty1 Thu Aug 18 07:38 - down (1+18:53)
reboot system boot 2.4.26 Thu Aug 18 07:23 (1+19:08)
laura tty1 Wed Aug 17 07:24 - down (15:22)
reboot system boot 2.4.26 Wed Aug 17 07:13 (15:33)
laura tty1 Tue Aug 16 07:30 - down (15:21)
etc....
[laura@cleopatra ~]$ cat sudamnit
#!/bin/bash

last;

function last() {
su - root -c "$(fc -ln -1 -1)";
}

What the heck is that log?
 
Old 08-23-2005, 09:30 AM   #9
theYinYeti
Senior Member
 
Registered: Jul 2004
Location: France
Distribution: Arch Linux
Posts: 1,897

Rep: Reputation: 66
I can't tell what this log file is (I'm not on linux right now), but IMHO, you should run the fc command in the same shell as the previous one. Maybe the command that gets executed is the last one, not counting those in the current shell, supposing the history is not inherited by child shells.

So you'd have to run ". sudamnit" instead of simply "sudamnit"; or (my prefered way) simply add this function to your .bashrc:
Code:
function sudamnit() {
  su root -c "$(fc -ln -1 -1)";
}
Note that I removed the '-' from the command, so that the environment stays the same (including $PWD), else a command like "ls ./tmp" would not repeat as expected.
Alternately, you could use this:
Code:
function sudamnit() {
  su - root -c "cd \"$PWD\"; echo \$PWD; $(fc -ln -1 -1)";
}
(the "echo ..." is of course optional)
By the way, for the record (future readers ), it is fc -<lowercase L>n -<number 1> -<number 1>.

Yves.
 
Old 08-23-2005, 11:15 AM   #10
rose_bud4201
Member
 
Registered: Aug 2002
Location: St Louis, MO
Distribution: Xubuntu, RHEL, Solaris 10
Posts: 929

Original Poster
Rep: Reputation: 30
Whoot A little more tweaking, and it works perfectly. The theoretical multiple shell/different histories problem shouldn't be much of an issue, as the command I want to run and the sudamnit command will be immediately sequential in the same shell.

So, here's how it ends up (slightly scrubbed of course):
Code:
[me@localhost ~]$ cat .bashrc
export PATH=$PATH:/usr/sbin/:/home/me/OpenOffice.org1.1.0/program:/usr/gnat/bin:/usr/java/jdk1.3.1_07/bin/
export PYTHONPATH=/usr/local/lib/python2.2/site-packages/gtk-2.0/:/usr/local/lib/python2.2/site-packages/
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig

#aliases
alias ls="ls --color"
alias ll="ls -lht"
alias umount="sudo umount"
alias mount="sudo mount"
alias shutdown="sudo /sbin/shutdown"
alias zork="~/Download/jzip201g/jzip ~/zork/zork_x/ZORK1.DAT"
alias azureus="~/azureus/azureus"

#Customize bash prompt to look human...
PS1="[\u@\h \w]\\$ "

#OMG MAKE THE BEEP GO AWAY
xset -b

# Because we can't all be root
function sudamnit() {
    command=$(fc -ln -1 -1);
    command=`echo $command | sed 's/^[ ]*//'`
    #echo "running 'su root -c \"$command'\""
    su root -c "$command";
}

#The last thing in the file
echo "What is your command, my mistress?"
[me@localhost ~]$ tail /var/log/messages
tail: cannot open `/var/log/messages' for reading: Permission denied
[me@localhost ~]$ sudamnit
Password:
Aug 23 08:11:55 localhost -- MARK --
Aug 23 08:31:55 localhost -- MARK --
Aug 23 08:50:02 localhost sshd[1726]: Accepted password for me from XXX.XXX.XXX.XXX port XXXX ssh2
Aug 23 09:11:55 localhost -- MARK --
Aug 23 09:31:55 localhost -- MARK --
Aug 23 09:51:55 localhost -- MARK --
Aug 23 10:11:55 localhost -- MARK --
Aug 23 10:31:55 localhost -- MARK --
Aug 23 10:51:55 localhost -- MARK --
Aug 23 10:57:33 localhost sshd[3106]: Accepted password for me from XXX.XXX.XXX.XXX port XXXX ssh2
[me@localhost ~]$

Thanks for all of your help in making this happen, all of you!
 
Old 08-23-2005, 12:49 PM   #11
stefanlasiewski
Member
 
Registered: Aug 2003
Location: Berkeley, California, USA
Distribution: Red Hat Enterprise Linux, Debian & Ubuntu
Posts: 92

Rep: Reputation: 16
Quote:
Originally posted by rose_bud4201
#!/bin/bash

last;

function last() {
su - root -c "$(fc -ln -1 -1)";
}

What the heck is that log?
Your script executes the command 'last' (/usr/bin/last) and THEN it defines a function called last(). That log is the output of the /usr/bin/last command.

To fix this, you should put the function definition before the function is executed. In addition, you should probably change the name of the function last() so it doesn't conflict with the command /usr/bin/last . Like this:

Code:
#!/bin/bash

# Define the function
function lastcommand() {
su - root -c "$(fc -ln -1 -1)";
}

# Execute the function
lastcommand;
Languages like Perl, PHP, C & Java all interpret and compile the program before it is executed. Therefore you can put the function definitions anywhere in the file, and you can execute the function anywhere in the file.

Shell scripts are much simpler, and run through the script in linear order.
 
Old 08-23-2005, 02:35 PM   #12
puffinman
Member
 
Registered: Jan 2005
Location: Atlanta, GA
Distribution: Gentoo, Slackware
Posts: 217

Rep: Reputation: 31
I think this has been a very useful discussion, and the result a useful command. Here is my version using sudo:

Code:
# d'oh!
function sudoh() {
    command=$(fc -ln -1 -1);
    command=`echo $command | sed 's/^[ ]*//'`
    echo "sudo $command"
    sudo $command
}
It is interesting that the last line cannot be sudo "$command", because then sudo will attempt to run any arguments as part of the actual name of the command.
 
Old 08-23-2005, 03:42 PM   #13
rose_bud4201
Member
 
Registered: Aug 2002
Location: St Louis, MO
Distribution: Xubuntu, RHEL, Solaris 10
Posts: 929

Original Poster
Rep: Reputation: 30
Quote:
Originally posted by stefanlasiewski
Your script executes the command 'last' (/usr/bin/last) and THEN it defines a function called last(). That log is the output of the /usr/bin/last command.
ah-ha! Now I learned a new command

Makes sense, though...as you could see I renamed it to just be the function 'sudamnit', although any name would have done.

It's also interesting that this has to be there:
Code:
command=`echo $command | sed 's/^[ ]*//'`
I tried it without that line at first, and it seems that whatever fc returns as the command is buffered with whitespace. Su just sat there, waiting for a command to be given. When it's stripped there isn't a problem.
 
Old 08-23-2005, 03:49 PM   #14
theYinYeti
Senior Member
 
Registered: Jul 2004
Location: France
Distribution: Arch Linux
Posts: 1,897

Rep: Reputation: 66
Interesting indeed. I like that. However, there's one issue I see: if your command or your arguments have spaces in them, this won't work, and as you said, putting quotes is not the answer. Here is the solution I propose:
Code:
function sudoh() {
  read -a words < <(fc -ln -1 -1)
  echo sudo "${words[@]}"
  sudo "${words[@]}"
}
Yves.
 
Old 11-21-2005, 04:14 PM   #15
theYinYeti
Senior Member
 
Registered: Jul 2004
Location: France
Distribution: Arch Linux
Posts: 1,897

Rep: Reputation: 66
For those still interested, here's a shorter and better version I wrote to address an important issue:
- I want to be able to rerun a sudo'd command.
New version (I put it in a new file in /etc/profile.d/):
Quote:
#!/bin/bash

alias redoEditor="sed -i 's/^/sudo /'"
alias redo='fc -e redoEditor -1'
Simple and to the point Example:
Code:
[yves@sedentaire ~]$ head -n 2 /root/.fetchmailrc
head: Ne peut ouvrir `/root/.fetchmailrc' en lecture: Permission non accorde
[yves@sedentaire ~]$ redo
sudo head -n 2 /root/.fetchmailrc
Password: <<<my password>>>
# Configuration created Fri Dec 21 22:41:15 2001 by fetchmailconf
set postmaster "yves"
[yves@sedentaire ~]$ history | tail -n 4
   81  head -n 2 /root/.fetchmailrc
   82  redo
   83  sudo head -n 2 /root/.fetchmailrc
   84  history | tail -n 4
[yves@sedentaire ~]$
so I can execute history entry number 83 if I need to, whereas history entry number 82 cannot be rerun (previous version did not create entry 83).

Yves.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How do I make a command run as root at boot up under Fedora 3? versaulis Linux - Software 5 02-10-2005 06:22 PM
Bash script - to save and run a command at the end satimis Programming 15 11-02-2004 08:53 AM
How to run a bash command in the background from perl script professorfrink Programming 3 11-13-2003 03:02 PM
Is their a way to run a command as root..or another user.. in php BaerRS Programming 2 04-25-2002 02:38 PM
Install scripts do not run...BASH# no such command tmera Linux - General 1 12-17-2000 02:33 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:54 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration