There might be an easier way of doing this, I'm going to be running a bunch of commands on a box. I want to keep track of the successful ones so that I can make a script out of it to automate this in the future.

I tried

<command> && echo "!!" >> file

but the !! is printing the line before this one. I've tried a few other things but can't get something to work

  • Is there some reason why you can't just look at your history? As in run history. – Zoredache Dec 17 '12 at 21:53
  • or use script...then remove the unsuccessfull commandes – Alex Dec 17 '12 at 21:59
  • history stores all input, not just succesful commands (or even just exit status) – Dennis Kaarsemaker Dec 17 '12 at 21:59
  • @Zoredache Um, I guess but wont this include unsuccessful commands too? and how will I know where the history I want to repeat begins? – GP89 Dec 17 '12 at 21:59
  • 1
    Shouldn't you log the unsuccessful commands instead? – Michael Hampton Dec 17 '12 at 21:59

You can do it like this:

PROMPT_COMMAND='[[ $? == 0 ]] && history 1 | sed -r "s/\ +[0-9]+\ +//" >> successful'

$PROMPT_COMMAND holds a command which bash executes before issuing a prompt. So what this does is evaluate the exit status of your previous command (after you press enter to execute your current command, but before bash evaluates it), and if it was successful, pull it from your bash history, strip the command number, and put add it to a separate file.

Now you don't have to tack on anything to your commands:

echo "exits successfully and will be appended"
ehco "only ends up in bash history"

Note that the readline history commands, !! and the rest of its family, only works in interactive shells, you cannot use those in scripts.

Also note that the -r option is gnu sed, bsd sed does not have it.

  • +1 this is awesome, although everything is getting appended, even the unsuccessful commands? That's fine I only plan to use the output in the successful file to make the script, so I wont be using !! for that. – GP89 Dec 18 '12 at 19:10
  • It helps if you test first :) Replace [[ $? ]] with [[ $? = 0 ]] to really make it only do succesful ones. – Dennis Kaarsemaker Dec 18 '12 at 19:10

I would use a second shell and strace. In shell 1, use echo $$ to find the PID of your shell. Then use strace -f -q -eexecve,exit_group -p that_pid_here to trace commands and exit statuses. The resulting output can then be mangled into a shellscript afterwards.

  • If I do this and try to use sudo in the other shell I get "sudo: must be setuid root". I'm starting to think this probably wasn't one of my best ideas.. lol – GP89 Dec 17 '12 at 22:08
  • 1
    try sudo strace and not strace sudo :) – Dennis Kaarsemaker Dec 17 '12 at 22:08
  • 1
    @DennisKaarsemaker the problem isn't sudo strace the problem is that once bash_shell_1 is being traced, setuid executables run inside that shell stop functioning right. See superuser.com/questions/247888/… – DerfK Dec 17 '12 at 23:40
  • yea I didn't try to run strace with sudo, while its running it prevents me from using sudo in the second shell – GP89 Dec 18 '12 at 19:02

This will do - note it is ' instead of "

<command> && echo '!!' >> file
  • This echos the literal string !! into the file, rather than <command> or the command on the previous line like "!!" did. – GP89 Dec 18 '12 at 19:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.