-1

Goal: Create a Posix compatible sh script that uses an environment variable created by a sourced script.

/dir/var.sh contains only the following to create an environment variable.

export IPTABLES="/usr/sbin/iptables"

/dir/startup.sh contains the following.

#!/bin/sh

. /dir/var.sh

$IPTABLES options

command1 #Does not use an environmental variable

After startup.sh completes, the variable is either not created or does not survive. Why ?

Note: the OS firmware is read-only. It does not allow editing the /etc/profile file to set environment variables to be available to all shells. Any script to export variables will execute too late.

xhienne
  • 17,793
  • 2
  • 53
  • 69
uihdff
  • 455
  • 2
  • 7
  • 17
  • A called script is very different from a sourced script. Your question says "called" but your code shows "sourced." Which do you want? – Wildcard Sep 19 '17 at 22:42
  • (Also, just based on the type of questions you are asking, you may be interested in using a mature configuration management tool such as CFEngine, the original purpose of which was to abstract away differences between *nix-like operating systems.) – Wildcard Sep 19 '17 at 22:43
  • No. You can call a script or you can source a script. They are completely different actions. See https://unix.stackexchange.com/q/65634/135943 – Wildcard Sep 19 '17 at 22:45
  • 2
    Your problem here is likely one of relative paths vs. absolute paths. The startup.sh script as written will only work correctly if you run it from the / directory (i.e. run cd / first). – Wildcard Sep 19 '17 at 22:50
  • There are other commands in the startup.sh script that execute correctly. Execution of the startup.sh script is controlled by the OS at bootup so I don't know where the working directory is. – uihdff Sep 19 '17 at 23:07
  • See previous comment. And carefully learn the following concepts: absolute path, relative path, current working directory (of a process). Then reread the command . ./dir/var.sh and see if you can spot what's wrong. – Wildcard Sep 19 '17 at 23:10
  • Okay, I'll spell it out: replace . ./dir/var.sh with . /dir/var.sh and your script will work. This has nothing to do with environment variables, only to do with paths. – Wildcard Sep 19 '17 at 23:22
  • 2
    This question isn't much different than the behavior of bashrc or profile files – OneCricketeer Sep 20 '17 at 00:13
  • 1
    IIUC, you want to create environment variables that would be available to all processes, including already started processes and processes that you don't start yourself. You cannot. In Unix, environment is inherited by processes. Thus, you must set your environment in a grand-...-grand-parent-process, which would probably be init itself, or an early init script. Since your firmware is read-only, you cannot do that. – xhienne Sep 20 '17 at 20:50
  • 1
    This question is misleading; your actual question is about creating a globally-available environment variable, but immediately dives in to talking about a sourced script that sets and exports a variable. – Jeff Schaller Sep 20 '17 at 21:31

1 Answers1

2

See the related Wikipedia page:

In Unix, an environment variable that is changed in a script or compiled program will only affect that process and possibly child processes. The parent process and any unrelated processes will not be affected.

Sourcing (*) is including a script in the current processing. Environment variables defined in your var.sh script are thus seen from the startup.sh script.

OTOH, startup.sh is called, not sourced. It's therefore a child process as mentioned in the WP page. All variables created in this script will be discarded when the script ends.

(*) source script.sh or . script.sh. As stated by others in the OP's comments, it is a bad idea to specify a relative path to the source script as you did with . ./dir/var.sh since it depends on the location where you are calling startup.sh from.

xhienne
  • 17,793
  • 2
  • 53
  • 69
  • This doesn't apply. Look closer. The variables defined in var.sh are not seen from startup.sh, because it's sourced with a relative path which is incorrect for the current working directory in which startup.sh is actually run. – Wildcard Sep 19 '17 at 23:24
  • 1
    @Wildcard How do you know the current working directory is not /? The question is "After startup.sh runs, the variables are not created or do not survive", not why IPTABLES is not defined in startup.sh. – xhienne Sep 19 '17 at 23:29
  • The question is badly and imprecisely written, but also note the statement in comments "there are other commands in the startup.sh script that execute correctly," implying that some do not. And as for creating a "sh script that uses an environment variable created by a called script," the environment variable is created by a sourced script, not a called script. So your mistake is understandable, but it just goes to show you shouldn't answer a question that needs further clarification. :) – Wildcard Sep 19 '17 at 23:37
  • 2
    @Wildcard Still not sure I misunderstood the question, but concur with the fact that the whole post is poorly written. OTOH the last question, the one I quoted above, is unambiguous. – xhienne Sep 19 '17 at 23:41
  • In a Windows environment, we say calling. In this example on Linux, I learned there is a distinction between the words calling and sourcing. The OP has been updated to reflect this. That said, changing to ". ./" to ". /" didn't fix the variables not being created or surviving. – uihdff Sep 19 '17 at 23:59
  • @uihdff Can you clarify your question and/or answer to Wildcard in the question's comments? You didn't accept my answer so I'm still unsure that I understood it well. – xhienne Sep 20 '17 at 00:03
  • @uihdff, a child process changing its own environment variables can never affect the environment of its parent—exactly as stated in the quote from Wikipedia in this answer. If what you really want is to set environment variables in a way that they will be available in any shell that you run, that's a completely different question and you should use an rc file or profile file of some sort, perhaps ~/.bashrc. – Wildcard Sep 20 '17 at 00:53