ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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!
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.
Distribution: Red Hat Enterprise Linux, Debian & Ubuntu
Posts: 92
Rep:
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
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?
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.
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)";
}
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>.
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!
Distribution: Red Hat Enterprise Linux, Debian & Ubuntu
Posts: 92
Rep:
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.
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.
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.
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[@]}"
}
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).
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.