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.
I'm looking for a good way of printing certain commands from a BASH script to STDOUT. This is going into a log file in the end. I don't want every command to be in there, just a few critical ones.
I know about
Code:
#!/usr/bin/bash -x
for echoing every command to the screen and also that I can do
Code:
set -x
some_command
set +x
to switch on the debugger for a single command.
The latter is what I'm using now but it produces a lot of annoying "+ set+x" lines in the output, because it will echo both, "some_command" and the next "set" command.
I would like to get rid of the redundant "+ set +x" lines.
My question: is there a better way of echoing commands to STDOUT then -x?
Only thing that comes to mind: echo the command(s):
Code:
#!/bin/bash
echo "ls ${cwd}/thefiles_*"
ls ${cwd}/thefiles_*
I still believe you might want to have a look at the tee command (in combination with the echo command). This way you can see what is happening as the script runs _and_ have a log file to check later on.
Thanks again druuna.
Yes, that can be done and I also used to do it like that but there are two problems:
1) duplication: it is very easy to change the command but forget to change the echo statment and the log will be wrong
2) to avoid 1, you would need to put the command into a variable and then use the variable to run the command. That works but I find myself in escape-and-quote hell very quickly, especially if you have longer commands where quoting and escaping is already a challange sometimes.
I guess the set -x option is probably the best for now. It works and I guess I might have to live with all those "set +x" lines in my log file for now.
Here are Greg's thoughts on the subject. I've tried using the array technique but it gets cumbersome; implementing it in a function would be tidier. AFAIK there's no way to use command history to get what you want.
Thanks a lot catkin, that blog post was exactly what I was looking for!
OK, from that I gather that set -/+x is the best solution already and I guess I have to live with those pesky "set +x" lines in my log and maybe remove them afterwards with grep. I think that's still better than copy/pasting the command, forgetting to update the echo statement and then wondering later why that command lead to that error where it was really a different command that caused it.
Thanks a lot catkin, that blog post was exactly what I was looking for!
OK, from that I gather that set -/+x is the best solution already and I guess I have to live with those pesky "set +x" lines in my log and maybe remove them afterwards with grep. I think that's still better than copy/pasting the command, forgetting to update the echo statement and then wondering later why that command lead to that error where it was really a different command that caused it.
Greg's WIKI is a great bash resource.
I can't think of a better solution than you have described. Not pretty but the best we can do with bash (until someone finds out differently -- there's always something to learn with bash )
Why not write a function that echoes the command before its execution? In this case if you change the command in a later revision of the script, the function will take care of recording the changes. Example:
Code:
function echo_cmd () {
echo "$PS4$@" 1>&2
"$@"
}
The only (not sure about this) caveat is to call the function for every command inside a piped chain, i.e.
which is exactly the same output as that one produced by set -x. Regarding redirection, it will be processed in the usual way and similarly to set -x the echoed command will be sent to standard error.
Edit: ok... found another caveat: command substitution is not treated as set -x, since it is performed by the invoking shell, not inside the function. Hmm... maybe this is not a good approach!
Last edited by colucix; 11-03-2010 at 09:31 AM.
Reason: More doubts......
colucix's solution works for bare commands but not for command substitution (as he has already mentioned) or for I/O redirection or for pipelines. It would be difficult to write a function that did deal with these; how would it deal with the apparently innocuous echo "|" foo or echo '$( ls ) > /tmp/ls.output' ? The function would have no way, passed a series of words that make up a command, to know if they were simply strings or if they had special meaning for command execution. Any sequence of characters are possible so no "escaping" to tell the function that "this word has a special meaning for command execution" is robustly possible and, even it it were "good enough" it would be messy for the calling code.
All-in-all, stripping the "set +x"s out of the log is simpler!
Last edited by catkin; 11-03-2010 at 10:13 AM.
Reason: Corrected "know" to "no"
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.