-1

I have a bash script that runs a bunch of other commands (e.g. docker). I want the script to be able to capture all the output into a variable and then echo out a custom return at the end.

Example:

#!/usr/bin/env bash
set -euo pipefail

# Capture into this (PSEUDO CODE)
declare CapturedOutput
$(Capture Output > CapturedOutput)

# Run some commands like...
docker-compose ... up -d

# Stop capturing (PSEUDO CODE)
$(Stop Capture Output > CapturedOutput)

echo "something"

So if someone called my script like ./runit.sh and the docker command had output, they wouldn't see it but would only see:

> ./runit.sh

something
Don Rhummy
  • 24,730
  • 42
  • 175
  • 330
  • Possible duplicate of [Capture output of a bash command, parse it and store into different bash variables](https://stackoverflow.com/questions/18450346/capture-output-of-a-bash-command-parse-it-and-store-into-different-bash-variabl) – Léa Gris Aug 14 '19 at 19:21
  • @LéaGris It's not a duplicate. That's capturing the output from outside the script. I want to capture it inside – Don Rhummy Aug 14 '19 at 19:22
  • Is it just the output of docker you want to capture in a variable? – David C. Rankin Aug 14 '19 at 19:29
  • 1
    Are you actually going to use `CapturedOutput`? Redirecting a command group to `/dev/null` might be sufficient. – chepner Aug 14 '19 at 19:33
  • @DavidC.Rankin No, I want to redirect the output of all the commands I run in the script – Don Rhummy Aug 15 '19 at 14:02

2 Answers2

1

The most straightforward way to capture output into a variable is to use command substitution. You can easily wrap that around a large chunk of script:

#!/usr/bin/env bash
set -euo pipefail

# To capture standard error, too:
# exec 3>&2 2>&1

CapturedOutput=$(

# Run some commands like...
docker-compose ... up -d

)

# To restore standard error:
# exec 2>&3- 

echo "something"

The caveat is that the commands from which output is being captured run in a subshell, but I'm having trouble coming up with an alternative for capturing into a variable in the same shell in which the commands themselves run.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Would this work differently than wrapping it all in a function? – Don Rhummy Aug 14 '19 at 20:49
  • I'm uncertain what specific alternative you have in mind, @DonRhummy. You *could* put `docker-compose` and all the other commands whose output is to be captured in a function, and that might indeed be a sensible thing to do, but you would still need to use command substitution -- either inside the function or of the function call -- to capture the output to a variable. – John Bollinger Aug 14 '19 at 21:45
  • Unfortunately, this sin't working. I *think* because it's in a subshell now, docker is unable to mount the volumes. I get the error: `ERROR: for redis Cannot start service redis: error while creating mount source path '/host_mnt/c/Users/myname/redis-test/customstartup.sh': mkdir /host_mnt/c: file exists` – Don Rhummy Aug 15 '19 at 14:01
  • @DonRhummy, I believe you that your particular script, written with use of a command substitution as I have described, does not successfully do the job you want it to do. It's not at all clear, however, why running the commands in a subshell would be directly responsible for the particular error described in that message, and in fact I find the prospect dubious. The issues with use of subshells largely revolve around (not) communicating information back to the parent shell, and especially around redirections and shell variable modifications performed in the subshell not affecting the parent. – John Bollinger Aug 15 '19 at 14:19
  • I know, but when I run it not in a subshell it works, but the moment I put it in a subshell it throws the error – Don Rhummy Aug 19 '19 at 16:11
  • Well, @DonRhummy, without a [mre] to study, there's not much I can say about why you're getting errors. The command substitution works for me with general commands. – John Bollinger Aug 19 '19 at 21:14
0

I think you want to look at the "Command Substitution" section on bash's man page.

To translate the pseudocode in your question to bash's format, something like:

CapturedOutput=$(docker-compose ... up -d)
CapturedOutput=$CapturedOutput $(docker-compose ... up -d)
...
Jeff Y
  • 2,437
  • 1
  • 11
  • 18