开发者

How to save the command you are about to execute in bash?

Is there a better way to save a command line before it it executed?

A number of my /bin/bash scripts construct a very long command line. I generally save the command line to a text file for easier debugging and (sometimes) execution.

My code is littered with this idiom:

echo >saved.tx开发者_Python百科t cd $NEW_PLACE '&&' command.py --flag $FOO $LOTS $OF $OTHER $VARIABLES
                cd $NEW_PLACE && command.py --flag $FOO $LOTS $OF $OTHER $VARIABLES

Obviously updating code in two places is error-prone. Less obvious is that Certain parts need to be quoted in the first line but not the next. Thus, I can not do the update by simple copy-and-paste. If the command includes quotes, it gets even more complicated.

There has got to be a better way! Suggestions?


How about creating a helper function which logs and then executes the command? "$@" will expand to whatever command you pass in.

log() {
    echo "$@" >> /tmp/cmd.log
    "$@"
}

Use it by simply prepending log to any existing command. It won't handle && or || though, so you'll have to log those commands separately.

log cd $NEW_PLACE && log command.py --flag $FOO $LOTS $OF $OTHER $VARIABLES


are you looking for set -x (or bash -x)? This writes every command to standard out after executing.


  1. use script and you will get archived everything.
  2. use -x for tracing your script, e.g. run them as bash -x script_name args....
  3. use set -x in your current bash (you will get echoed your commands with substitued globs and variables
  4. combine 2 and 3 with the 1


If you just execute the command file immediately after creating it, you will only need to construct the command once, with one level of escapes.

If that would create too many discrete little command files, you could create shell procedures and then run an individual one.

(echo fun123 '()' {
 echo echo something important
 echo }
) > saved.txt
. saved.txt
fun123


It sounds like your goal is to keep a good log of what your script did so that you can debug it when things go bad. I would suggest using the -x parameter in your shebang like so:

#!/bin/sh -x
# the -x above makes bash print out every command before it is executed.
# you can also use the -e option to make bash exit immediately if any command
# returns a non-zero return code.

Also, see my answer on a previous question about redirecting all of this debug output to a log when --log is passed into your shell script. This will redirect all stdout and stderr. Occasionally, you'll still want to write to the terminal to give the user feedback. You can do this by saving stdout to a new file descriptor and using that with echo (or other programs):

exec 3>&1  # save stdout to fd 3

# perform log redirection as per above linked answer

# now all stdout and stderr will be redirected to the file and console.
# remove the `tee` command if you want it to go just to the file.

# now if you want to write to the original stdout (i.e. terminal)
echo "Hello World" >&3

# "Hello World" will be written to the terminal and not the logs.


I suggest you look into the xargs command. It was made to solve the problem of programtically building up argument lists and passing them off to executables for batch processing

http://en.wikipedia.org/wiki/Xargs

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜