I am try to write regression tests using expect for an interactive bash script.
So far everything works Ok. I spawn the process with the correct arguments, and then send/expect.
I would like, during tests, to enable tracing in the bash script, using the set -x command. However, when doing so, the bash trace output messes with expect.
I would like expect to ignore those lines when performing matching but still output them on either stdout or stderr.
Apperently, there is so way to treat stderr and stdout independently.
I have already tried a few thing using expect_before and expect_background, but none having given me good results.
Any thoughts ?
Thanks.
If the output (I mean non-trace output) from your bash script if well-defined, you can simply ignore the trace output when using expect command. For example, if your script shows:
+ echo 'Password:'
Password:
you can use regexp mode of expect:
expect -re '^Password:'
That would ignore the trace output but match the password prompt. Granted, your match rules should be very tight to not match any undesirable output.
Related
I have a bash script that is using xmlstarlet to manipulate some key/value pairs in an application configuration file to prepare the file to be moved to a new production host. The values that need changed are host/encryption specific.
In order to discover one of the new values I need to interact with a vendor provided script in an expect session and capture the output into a variable in the bash script so I can continue to use it.
The expect part of the bash script looks something like this:
expect <<DONE
spawn command_provided_by_vendor
expect :
send -- "newvalue\r"
DONE
This is where I get stuck
In a shell the output of this command looks like:
Encrypted value (case sensitive, please cut and paste): 2qIrRvcSoHMb55dpcef6vw==
What I need to do is capture the non-whitespace output after the ":" and nothing I've tried works due to regexp errors, the parenthesis in the prompt string, etc.
There are other questions on stackoverflow that are similar, but I failed to understand how those answers helped my problem.
Any help, pointers appreciated.
I would use the expect command to look for an appropriate regular expression and capture the value there:
value=$(
expect <<DONE
spawn command_provided_by_vendor
expect :
send -- "newvalue\r"
expect -re {Encrypted value.*: (\S+)}
puts $expect_out(1,string)
expect eof
DONE
)
I am trying to get the result from /usr/lib/update-notifier/apt-check on a Ubuntu 16 Server into a Array to make a XML response for a monitoring tool, but somehow the value of this apt-check just refuses to get in my Variable. For simplicity sake, I have omitted the XML creation part.
#!/bin/bash
APTCHECK="/usr/lib/update-notifier/apt-check"
APTResult="$(${APTCHECK})"
echo "Result is $APTResult"
exit 0
if you now run this code with bash -x you will see that the result is returned to the Terminal, but not assigned to the Variable. If I substitute the "command" to something simple like "ls -lah" everything works fine.
I just don't know why this is not working ? Anybody ?
apt-check prints to the stderr, so you need to capture that instead with aptresult=$(/usr/lib/update-notifier/apt-check 2>&1).
The other option is with the --human-readable switch, which'll print to the stdout. The only problem then is that you have to parse the text output (unless the text output is what you actually want).
I'm using a bash script to automatically run a simulation program. This program periodically prints the current status of the simulation in the console, like "Iteration step 42 ended normally".
Is it possible to abort the script, if the console output is something like "warning: parameter xyz outside range of validity"?
And what can I do, if the console output is piped to a text file?
Sorry if this sounds stupid, I'm new to this :-)
Thanks in advance
This isn't an ideal job for Bash. However, you can certainly capture and test STDOUT inside a Bash iteration loop using an admixture of conditionals, grep-like tools, and command substitution.
On the other hand, if Bash isn't doing the looping (e.g. it's just waiting for an external command to finish) then you need to use something like expect. Expect is purpose-built to monitor output streams for regular expressions, and perform branching based on expression matches.
I'm trying this in ruby.
I have a shell script to which I can pass a command which will be executed by the shell after some initial environment variables have been set. So in ruby code I'm doing this..
# ruby code
my_results = `some_script -allow username -cmd "perform_action"`
The issue is that since the script "some_script" runs "perform_action" in it's own environment, I'm not seeing the result when i output the variable "my_results". So a ruby puts of "my_results" just gives me some initial comments before the script processes the command "perform_action".
Any clues how I can get the output of perform_action into "my_results"?
Thanks.
The backticks will only capture stdout. If you are redirecting stdout, or writing to any other handle (like stderr), it will not show up in its output; otherwise, it should. Whether something goes into stdout or not is not dependent on an environment, only on redirection or direct writing to a different handle.
Try to see whether your script actually prints to stdout from shell:
$ some_script -allow username -cmd "perform_action" > just_stdout.log
$ cat just_stdout.log
In any case, this is not a Ruby question. (Or at least it isn't if I understood you correctly.) You would get the same answer for any language.
Is there a way to log the commands, make invokes to compile a program? I know of the parameters -n and -p, but they either don't resolve if-conditions but just print them out. Or they don't work, when there are calls to 'make' itself in the Makefile.
This
make SHELL="sh -x -e"
will cause the shell (which make invokes to evaluate shell constructs) to print information about what it's doing, letting you see how any conditionals in shell commands are being evaluated.
The -e is necessary to ensure that errors in a Makefile target will be properly detected and a non-zero process exit code will be returned.
You could try to log execve calls with strace
strace -f -e execve make ...
Make writes each command it executes to the console, so
make 2>&1 | tee build.log
will create a log file named build.log as a side effect which contains the same stuff written to the screen. (man tee for more details.)
2>&1 combines standard output and errors into one stream. If you didn't include that, regular output would go into the log file but errors would only go to the console. (make only writes to stderr when a command returns an error code.)
If you want to suppress output entirely in favor of logging to a file, it's even simpler:
make 2>&1 > build.log
Because these just capture console output they work just fine with recursive make.
You might find what you're looking for in the annotated build logs produced by SparkBuild. That includes the commands of every rule executed in the build, whether or not "#" was used to prevent make from printing the command-line.
Your comment about if-conditions is a bit confusing though: are you talking about shell constructs, or make constructs? If you mean shell constructs, I don't think there's any way for you to get exactly what you're after except by using strace as others described. If you mean make constructs, then the output you see is the result of the resolved conditional expression.
Have you tried with the -d parameter (debug)?
Note that you can control the amount of infos with --debug instead. For instance, --debug=a (same as -d), or --debug=b to show only basic infos...