0

I have a command line too that produce result like such

$ mytool --param 2579072
TOO_ENV1=123456
TOOL_ENN2=df73ddb

its being used in a seperate script to set up some env var

#!/usr/bin/env bash

set -eo pipefail
...
echo "set up env variables"
source <(mytool --param "${pr_param}")

this used to work but after upgrading to a new machine (mac Big Sur) it stops working? I now am doing export $(mytool --param "${pr_param}" | xargs) instead

I am curious of why the source way is not working anymore? any guess?


update:

before

GNU bash, version 4.4.23(1)-release (x86_64-apple-darwin17.7.0)
Copyright (C) 2016 Free Software Foundation, Inc.

now bash version is

GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20)
Copyright (C) 2007 Free Software Foundation, Inc.
OLIVER.KOO
  • 5,654
  • 3
  • 30
  • 62
  • Note that `TOO_ENV1=123456` doesn't set up an _environment_ variable at all. It creates a regular, non-exported shell variable, unless you modified your shell with something like `set -a` to enable auto-export. – Charles Duffy Apr 20 '21 at 22:45
  • Also, note that `set -e` is... not universally considered good practice. See [BashFAQ #105](https://mywiki.wooledge.org/BashFAQ/105) -- if the allegory at the top is more than you have time for, skip down to the exercises below and see if you really think the behavior with `set -e` set is more reasonable and predictable than how the shell behaves without it. https://www.in-ulm.de/~mascheck/various/set-e/ also shows how wildly incompatible different shells' implementation of `errexit` behavior is. – Charles Duffy Apr 20 '21 at 22:47
  • 1
    Anyhow -- there _are_ some specific versions of bash that have historically had problems with passing `source` a process substitution, but without knowing exactly which version of bash you're running with, I can't say if you have one of those. And without seeing how you test if the variables are set, I don't know if you're requiring them to be exported (and thus visible from subprocesses); if you're expecting them to be relayed back to the parent; etc. – Charles Duffy Apr 20 '21 at 22:47
  • I don't have a `set -a` nor `set -o allexport` before, unsure why it was working..... – OLIVER.KOO Apr 20 '21 at 22:48
  • Even if you didn't have it in your script itself before, shell options can be exported into the environment and set on newly-created shells, so that's one possibility. Would really need to inspect the system where behavior is seen to run down the details. – Charles Duffy Apr 20 '21 at 22:51
  • Anyhow -- have you confirmed that the variable is being set but not exported? If so, that rules out the `source` bug I referenced, and means we need to look at how/why `allexport` was set in the old environment. – Charles Duffy Apr 20 '21 at 22:52
  • 1
    (Personally, btw, I'd `eval "$(mytool)"` -- that's an idiom with long history, being f/e how `ssh-agent` is expected to be called -- but you'll want to have `mytool` emit `export` directives rather than bare assignments; also, pay attention to making sure output is escaped safely -- `printf %q` is your friend for avoiding injection attacks when generating strings to be `eval`ed). – Charles Duffy Apr 20 '21 at 22:54
  • updated the question to include the bash version – OLIVER.KOO Apr 20 '21 at 22:55
  • Okay, so there's your problem: You had a newer bash instealled with Macports or Homebrew or Nixpkgs or somesuch, and now you have the stock Apple one. (Apple has _never_ shipped bash 4.0 or newer, since it's licensed under GPLv3 terms and they're unwilling to comply) – Charles Duffy Apr 20 '21 at 22:55
  • I am a noob to shell scripting. You are obviously a wizard. Sounds like this is a bug with bash 3 ? I am not sure if I get what you mean by suing eval or printf? – OLIVER.KOO Apr 20 '21 at 22:59
  • 1
    So, changing from `source <(mytool --param "$pr_param")` to `eval "$(mytool --param "$pr_param")"` will work around the bash 3 bug here – Charles Duffy Apr 20 '21 at 23:02
  • 1
    The `printf` discussion was more an aside about writing the `mytool` command safely. Let's say it does something like `echo "TOO_ENV=$(curl http://example.com/TOO_ENV)"` -- that's not safe to `eval` or to `source`, because what if the remote server comes back with a string with `; rm -rf ~` or `'$(rm -rf ~)'$(rm -rf ~)` in it? But what you _can_ do safely inside `mytool` is `printf 'export %q=%q\n' TOO_ENV "$(curl http://example.com/TOO_ENV)"`, because the `printf` tells the shell to convert the strings into a safe-to-eval format. – Charles Duffy Apr 20 '21 at 23:04
  • 1
    (if `mytool` is written in Python, the equivalent of bash's `printf %q` in Python 2 is `pipes.quote()`, or in Python 3, `shlex.quote()`; if it's in another language you'd need to look around for something similar). – Charles Duffy Apr 20 '21 at 23:05

0 Answers0