Bash script to read output of 'openssl help' - string

I try to read the output of the bash command 'openssl help' and put it in a string variable for further processing.
To be precise I want to test all Cipher commands.
First I tried to read the output of the command 'openssl ciphers'. But I got only ciphers and not the cipher commands. But if I type 'openssl help' then the cipher commands are shown. The problem is that now the output of the command is not saved in my variable.
CIPHER=`openssl ciphers`
echo "Output:"
echo $CIPHER
This works. But unfortunately the content of $CIPHER is not what I need.
CIPHER=`openssl help`
echo "Output:"
echo $CIPHER
This doesnt work. The variable CIPHER is empty. Why??

It does seem openssl help contents are written to the standard error stream stderr(2) instead of stdout(1). Suggest re-redirecting the error stream (represented by file descriptor 2) to standard output(represented by file descriptor 1) to fix the issue.
Since the output contains a multi-line stream, recommend enclosing the $(..) command-substitution over backticks (outdated technique) with proper double-quotes.
sslOutput="$(openssl help 2>&1)"
printf "%s\n" "${sslOutput}"
See why $(..) is prefereed over legacy .. syntax for command substitution.

Related

How do i use other command in the same line with echo

I want to use a command to be printed on the same line as the string.
for example, i want to print something like:
hostname: cpu1
but when i use the command like this it doesnt work
echo 'hostname:' hostname
You need to use $() to evaluate:
echo 'hostname:' $(hostname)
Two answers are already given saying that you "need to" and "should" use command substitution by doing:
echo "hostname: $(hostname)"
but I will disagree with both. Although that works, it is aesthetically unappealing. That command instructs the shell to run hostname and read its output, and then pass that output as part of the argument to echo. But all that work is unnecessary. For this simple use case, it is "simpler" to do:
printf "hostname: "; hostname
(Using printf to suppress the newline, and avoiding echo -n because echo really should be treated as deprecated). This way, the output of hostname goes directly to the shell's stdout without any additional work being done by the shell. I put "simpler" in quotes because an argument could be made that humans find printf "hostname: %s\n" "$(hostname)" or echo "hostname: $(hostname)" to be simpler, and perhaps looking at much code that does things that way warps your mind and even makes it look simpler, but a few moments reflection should reveal that indeed it is not.
OTOH, there are valid reasons for collecting the output and writing the message with echo/printf. In particular, by doing it that way, the message will (most likely) be written with one system call and not be subject to interleaving with messages from other processes. If you printf first and then execute hostname, other processes' data may get written between the output of printf and the output of hostname. As always, YMMV.
This is what you should do:
echo "hostname: `hostname`"
Words enclosed in backticks are read by the command line as commands even when they are inside a string, like in this case.
Have a great day! :)

Unix: What does cat by itself do?

I saw the line data=$(cat) in a bash script (just declaring an empty variable) and am mystified as to what that could possibly do.
I read the man pages, but it doesn't have an example or explanation of this. Does this capture stdin or something? Any documentation on this?
EDIT: Specifically how the heck does doing data=$(cat) allow for it to run this hook script?
#!/bin/bash
# Runs all executable pre-commit-* hooks and exits after,
# if any of them was not successful.
#
# Based on
# http://osdir.com/ml/git/2009-01/msg00308.html
data=$(cat)
exitcodes=()
hookname=`basename $0`
# Run each hook, passing through STDIN and storing the exit code.
# We don't want to bail at the first failure, as the user might
# then bypass the hooks without knowing about additional issues.
for hook in $GIT_DIR/hooks/$hookname-*; do
test -x "$hook" || continue
echo "$data" | "$hook"
exitcodes+=($?)
done
https://github.com/henrik/dotfiles/blob/master/git_template/hooks/pre-commit
cat will catenate its input to its output.
In the context of the variable capture you posted, the effect is to assign the statement's (or containing script's) standard input to the variable.
The command substitution $(command) will return the command's output; the assignment will assign the substituted string to the variable; and in the absence of a file name argument, cat will read and print standard input.
The Git hook script you found this in captures the commit data from standard input so that it can be repeatedly piped to each hook script separately. You only get one copy of standard input, so if you need it multiple times, you need to capture it somehow. (I would use a temporary file, and quote all file name variables properly; but keeping the data in a variable is certainly okay, especially if you only expect fairly small amounts of input.)
Doing:
t#t:~# temp=$(cat)
hello how
are you?
t#t:~# echo $temp
hello how are you?
(A single Controld on the line by itself following "are you?" terminates the input.)
As manual says
cat - concatenate files and print on the standard output
Also
cat Copy standard input to standard output.
here, cat will concatenate your STDIN into a single string and assign it to variable temp.
Say your bash script script.sh is:
#!/bin/bash
data=$(cat)
Then, the following commands will store the string STR in the variable data:
echo STR | bash script.sh
bash script.sh < <(echo STR)
bash script.sh <<< STR

ask about the meaning of a bash script

I have a shell script application.sh, as follows.
#! /bin/busybox sh
set -o nounset -o errexit
readonly emul_script="/usr/local/bin/emul.sh"
readonly profile="/etc/vendor/profile"
source "${profile}"
_usage() {
cat << EOF
${0} [-d]
-d :debug
EOF
The above script starts a specific application. My question is related to the part starting from _usage, I do not quite understand what it means and cannot see how it is used.
The << is the heredoc construct and cats everything up to the end marker (EOF in this case) to stdout.
The ${0} is the name of the input file and this will print something like the following to stdout:
application.sh [-d]
-d :debug
You are missing the trailing } by the way.
Adding to what trojanfoe says, _usage() is a shell function.
But it is never called, nor is the application itself called, so I suppse that is only part of a script.
The _usage function might be called from ${profile} script that is sourced just above it.
Beware, that you may want to put it before the source line, because, strictly speaking, it has to be defined before it is used.

KornShell (ksh) redirection

I have a script which redirects std out/std err as below:
SCRIPTS=/test/scripts
LOG=/test/log
echo $SCRIPTS
echo $LOG
$SCRIPTS/dmm_algo_ofac_daily_sched.ksh >> $LOG/test12.log 2>&1
This script is not able to expand $SCRIPTS and $LOG
If I replace it as below:
/test/scripts/daily_sched.ksh >> /test/log/test12.log 2>&1
It complains as below:
: bad file unit numberd/test.ksh: line 33: 1
Also I am not able to invoke the script from the directory where it is saved. If I do
./test.ksh it gives me error saying file not found. I am able to execute it via ksh /test/sched/test.ksh though.
Can someone help me with these. Thanks in advance.
I'm almost certain that the problem is because of DOS/Windows line endings
The error message you are getting is overwriting itself because of a carriage return. You can fix your file using dos2unix.
Add magic #!/bin/ksh to the first line to invoke directly without naming the interpreter on the command line.
I'll conjecture wildly that your root cause(s) has (have) nothing to do with redirection.
Is the script you've exhibited /test/sched/test.ksh or /test/scripts/test.ksh? Are you certain?

Is it possible to make stdout and stderr output be of different colors in XTerm or Konsole?

Is it even achievable?
I would like the output from a command’s stderr to be rendered in a different color than stdout (for example, in red).
I need such a modification to work with the Bash shell in the Konsole, XTerm, or GNOME Terminal terminal emulators on Linux.
Here's a solution that combines some of the good ideas already presented.
Create a function in a bash script:
color() ( set -o pipefail; "$#" 2>&1>&3 | sed $'s,.*,\e[31m&\e[m,' >&2 ) 3>&1
Use it like this:
$ color command -program -args
It will show the command's stderr in red.
Keep reading for an explanation of how it works. There are some interesting features demonstrated by this command.
color()... — Creates a bash function called color.
set -o pipefail — This is a shell option that preserves the error return code of a command whose output is piped into another command. This is done in a subshell, which is created by the parentheses, so as not to change the pipefail option in the outer shell.
"$#" — Executes the arguments to the function as a new command. "$#" is equivalent to "$1" "$2" ...
2>&1 — Redirects the stderr of the command to stdout so that it becomes sed's stdin.
>&3 — Shorthand for 1>&3, this redirects stdout to a new temporary file descriptor 3. 3 gets routed back into stdout later.
sed ... — Because of the redirects above, sed's stdin is the stderr of the executed command. Its function is to surround each line with color codes.
$'...' A bash construct that causes it to understand backslash-escaped characters
.* — Matches the entire line.
\e[31m — The ANSI escape sequence that causes the following characters to be red
& — The sed replace character that expands to the entire matched string (the entire line in this case).
\e[m — The ANSI escape sequence that resets the color.
>&2 — Shorthand for 1>&2, this redirects sed's stdout to stderr.
3>&1 — Redirects the temporary file descriptor 3 back into stdout.
Here's an extension of the same concept that also makes STDOUT green:
function stdred() (
set -o pipefail;
(
"$#" 2>&1>&3 |
sed $'s,.*,\e[31m&\e[m,' >&2
) 3>&1 |
sed $'s,.*,\e[32m&\e[m,'
)
You can also check out stderred: https://github.com/sickill/stderred
I can't see that there is any way for the terminal emulator to do this.
The interface between the terminal emulator and the shell/app is via a pseudo-tty, where the terminal emulator is on the master side and the shell/app on the other. The shell/app have both stdout and stderr connected to the same pty, so when the terminal emulator reads from the pty for the shell/app output it can no longer tell which was written to stdout and which to stderr.
You will have to use one of the solutions that intercepts the data between the application and the slave-pty and inserts escape codes to control the terminal output colo(u)r.
Here is a little Awk script that will print everything you pass it in red.
#!/usr/bin/awk -f
{ printf("%c[%dm%s%c[0m\n", 0x1B, 31, $0, 0x1B); fflush() }
It simply prints each line it receives on stdin within the necessary escape codes to display it in red. It is followed by an escape code to reset the terminal.
(If you need a different color, change the second argument in the above printf call from 31 to the number corresponding to the desired color.)
Save it to colr.awk, do a chmod a+x, and use it like so:
$ my_program | ./colr.awk
It has the drawback that lines may not be displayed in order, because stderr goes directly to the console, while stdout is piped through an additional process.
A simple solution to color stdout in red is to pipe it through grep:
program | grep .
This should not require installing anything, as grep should be already installed everywhere.
Taken from Dennis’s comment on superuser.com.
I think you should use the standard escape sequences on stderr. Have a look at this.
Hilite will do this. It's a lightweight solution, but you have to invoke it for each command, eg. hilite gcc myprog.c. A more radical approach is built in to my experimental shell Gush which shows stderr from all commands run in red, stdout in black. Either way is very useful for software builds where you have lots of output with a few error messages that could easily be missed if not highlighted.

Resources