2

I have a script that exports some variables and in some places uses sudo.

This is a simple example:

export Name=John
sudo envsubst < SourceFile > TargetFile

And if the SourceFile has a $Name variable in it, then it would be printed as empty.

If I remove sudo then it works.

Does export work universally for all users? How can I export a variable for the entire machine?

Kusalananda
  • 333,661
Ali EXE
  • 129
  • 1
    It's unclear what the question is. Is it why the sudo command does not work (see System environment variables not appearing in sudo or similar questions), or is it about setting an environment variable for all users? Also note that export creates an environment variable that will be visible by the current shell and any child processes, unless they explicitly delete the variable (like sudo does). There is no way to "export to the whole machine". – Kusalananda Jan 11 '23 at 08:51

1 Answers1

10

By default, sudo clears its environment except for a few variables that it passes along sanitised (and a few that it explicitly sets to sane values) as a security measure.

If allowed by the sudo configuration, you may be able to use the -E/--preserve-env variable to work around that.

In any case, environment variables, like command arguments, is something that is passed from command to command upon execution, it's not something that lives in some ethereal space accessed by every process (for that, there's the file system), so exporting a variable for the entire machine doesn't make sense.

Also, the envsubst command doesn't need any special privilege so it doesn't make sense to run it as root. If you're doing that in an attempt to open the source file or create the target file as root, that's misguided because in:

sudo envsubst < SourceFile > TargetFile

The redirections are done by the shell invoking sudo so as the original user.

It's a command that opens those files that you'd need to run as root:

sudo cat SourceFile | envsubst | sudo sh -c 'exec cat > TargetFile'

Here using cat to open (and read and pass along) the SourceFile, and sh to open the TargetFile (and cat writing the data there).

If on a GNU system, you could also do:

sudo dd bs=64k status=none if=SourceFile |
  envsubst |
  sudo dd bs=64k status=none of=TargetFile

See Does Unix have a command to read from stdin and write to a file (like tee without sending output to stdout)? for details and other approaches.