How to echo shell commands as they are executed?

2019-01-03 19:15发布

In a shell script how do I echo all shell commands called and expand any variable names? For example, given the following line:

ls $DIRNAME

I would like the script to run the command and display the following

ls /full/path/to/some/dir

The purpose is to save a log of all shell commands called and their arguments. Perhaps there is a better way of generating such a a log?

标签: shell
14条回答
聊天终结者
2楼-- · 2019-01-03 19:33

For zsh echo

 setopt VERBOSE

and for debugging

 setopt XTRACE
查看更多
三岁会撩人
3楼-- · 2019-01-03 19:35

You can also toggle this for select lines in your script by wrapping them in set -x and set +x e.g.

#!/bin/bash
...
if [[ ! -e $OUT_FILE ]];
then
   echo "grabbing $URL"
   set -x
   curl --fail --noproxy $SERV -s -S $URL -o $OUT_FILE
   set +x
fi
查看更多
时光不老,我们不散
4楼-- · 2019-01-03 19:40

I use a function to echo then run the command

#!/bin/bash
#function to display commands
exe() { echo "\$ $@" ; "$@" ; }

exe echo hello world

Which outputs

$ echo hello world
hello world

Edit:

For more complicated commands pipes etc you can use eval:

#!/bin/bash
#function to display commands
exe() { echo "\$ ${@/eval/}" ; "$@" ; }

exe eval "echo 'Hello World' | cut -d ' ' -f1"

Which outputs

$  echo 'Hello World' | cut -d ' ' -f1
Hello
查看更多
姐就是有狂的资本
5楼-- · 2019-01-03 19:41

According to TLDP's Bash Guide for Beginners: Chapter 2. Writing and debugging scripts

2.3.1. Debugging on the entire script

$ bash -x script1.sh

...

There is now a full-fledged debugger for Bash, available at SourceForge. These debugging features are available in most modern versions of Bash, starting from 3.x.

2.3.2. Debugging on part(s) of the script

set -x            # activate debugging from here
w
set +x            # stop debugging from here

...

Table 2-1. Overview of set debugging options

Short  | Long notation | Result  
-------+---------------+--------------------------------------------------------------
set -f | set -o noglob | Disable file name generation using metacharacters (globbing).  
set -v | set -o verbose| Prints shell input lines as they are read.  
set -x | set -o xtrace | Print command traces before executing command.  

...

Alternatively, these modes can be specified in the script itself, by adding the desired options to the first line shell declaration. Options can be combined, as is usually the case with UNIX commands:

#!/bin/bash -xv
查看更多
祖国的老花朵
6楼-- · 2019-01-03 19:41

Someone above posted:

#!/bin/bash
#function to display commands
exe() { echo "\$ $@" ; "$@" ; }

and this looks promising, but I can't for the life of me figure out what it does. I've googled and searched in the man bash page for "\$" and "$@", and find absolutely nothing.

I understand a function is being created, named "exec()". I understand the curly-brackets mark the beginning and end of the function. I think I understand that the semi-colon marks a "hard return" between a multi-line command, so that '{ echo "\$ $@" ; "$@" ; }' becomes, in essence:

{
echo "\$ $@"
"$@"

}

Can any one give me a brief explanation, or where to find this info, since obviously my google-fu is failing me?

(Without meaning to start a new question on an old thread, my goal is to reroute the output to a file. The "set -x ; [commands] ; set +x" method would work adequately well for me, but I can't figure out how to echo the results to a file instead of the screen, so I was trying to understand this other method in hopes I could use me very poor understanding of redirection/pipes/tee/etc to do the same thing.)

Thanks!

LATER EDIT:

With some tinkering, I believe I figured it out. Here's my equivalent code for what I'm needing:

SCRIPT_LOG="\home\buddy\logfile.txt"
exe () {
  params="$@"                       # Put all of the command-line into "params"
  printf "%s\t$params" "$(date)" >> "$SCRIPT_LOG"   # Print the command to the log file
  $params                           # Execute the command
}

exe rm -rf /Library/LaunchAgents/offendingfile
exe rm -rf /Library/LaunchAgents/secondoffendingfile

The results in the logfile.txt look something like:

Tue Jun  7 16:59:57 CDT 2016  rm -rf /Library/LaunchAgents/offendingfile
Tue Jun  7 16:59:57 CDT 2016  rm -rf /Library/LaunchAgents/secondoffendingfile

Just what I needed. Thanks!

查看更多
叼着烟拽天下
7楼-- · 2019-01-03 19:43

You can execute a bash script in debug mode with the -x option.
This will echo all the commands.

bash -x example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt


You can also save the -x option in the script. Just specify the -x option in the shebang.

######## example_script.sh ###################
#!/bin/bash -x

cd /home/user
mv text.txt mytext.txt

##############################################

./example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt



查看更多
登录 后发表回答