1

I want to store a variable that keeps its value even after the execution is complete. I found out one way I can do that is by making a variable an environment variable. But it does seem to work like I want it to.

I want something like this.

init() {
  if [[ -z $package_version ]]; then
    package_version="v.0.0.1"
    exoprt package_version
  fi
}

Let's Say I run this code will set a version number but if it is run the second time it should not execute that if block.

How can I achieve this?

updated: I want to create a sqlite database having multiple tables each table is associated with different profiles. I want the user to choose a profile or switch profiles. Now I should contain this profile info if the user wants to fetch or enter details into the particular database with the help of the profile which I want to store the value and keep after the execution is complete.

S_coderX451
  • 95
  • 1
  • 7
  • 5
    You need to source the script and not start a new interpreter when you run it. – Ted Lyngmo Apr 03 '23 at 11:10
  • 3
    Also fix `exoprt` and see [correct-bash-and-shell-script-variable-capitalization](https://stackoverflow.com/questions/673055/correct-bash-and-shell-script-variable-capitalization). – Ed Morton Apr 03 '23 at 11:12
  • @TedLyngmo But if I give the same file as the source it's leading to a segmentation fault. – S_coderX451 Apr 03 '23 at 12:29
  • @S_coderX451 To _source_ a script is not the same as giving the script itself as an argument. `source script.sh` (or `. script.sh`) – Ted Lyngmo Apr 03 '23 at 12:40
  • A segmentation fault sounds like there is some C or C++ code involved here. You should edit your question to include an example of that and how the two programs are interacting with each other (is the C code calling this script or vice-versa?) – tjm3772 Apr 03 '23 at 13:43
  • 3
    You have a fundamental misunderstanding how env vars work. They are private to each process. When a process exits its env vars disappear. When a process is started it normally inherits a copy of the env vars of its parent process. If you want the env var to be persistent you have to store it someplace like your *~/.bashrc* script or */etc/environment*. – Kurtis Rader Apr 03 '23 at 16:04
  • @KurtisRader So I want a variable to store some state and keep it after the execution is complete. And that state will be used by the same program. Is it possible? – S_coderX451 Apr 03 '23 at 16:46
  • @tjm3772 lets suppose my code is `source ./test.sh if [[ $GLOBAL -eq 10 ]]; then echo "Nothing" echo $GLOBAL fi if [[ -z $GLOBAL ]]; then echo "Export" export GLOBAL=10 fi` this is leading to `[1] 62168 segmentation fault (core dumped) ./test.sh` – S_coderX451 Apr 03 '23 at 16:53
  • 2
    @S_coderX451: You probably **do not** want to use env vars for this. Env vars were never intended to be used in the manner you describe. You should instead use something like the "dotenv" mechanism (google "dotenv bash"). It is hard to provide a more useful answer because your example does not require persisting the result. So either your example does not reflect your real problem or you have left out important information. This seems like an [XY Problem](https://xyproblem.info/). – Kurtis Rader Apr 04 '23 at 02:03
  • How are these databases and/or profiles connected with `package_version`? – Craig H Apr 09 '23 at 00:44

1 Answers1

0

A lot of the comments raise valid concerns, but here is something that might "work" for your situation:

init() {
  # We choose to save our persistant variables file in the same directory
  # as the script. We could also save them in ~/.config/my-fun-script or
  # elsewhere.
  local vars_dir="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
  local vars_file="${vars_dir}/.vars-package-version.bash"

  # If we use a ~/.config/my-fun-script/config.bash file, we need to
  # make sure the directory is created.
  mkdir -p "$vars_dir"

  # Source the variable file if it exists.
  if [[ -f "$vars_file" ]]; then
    . "$vars_file"
  fi

  if [[ -z "$package_version" ]]; then
    package_version="v.0.0.1"
    # Save the variable file. We modify the declare line to add the -g
    # option. This ensures that when we source the variable, next time, from
    # within this function, it will be a global. That means that it is
    # accessible outside this function.
    declare -p package_version | sed 's/declare/declare -g/' >"$vars_file"
  fi
}

Note that setting the "export" flag on a variable only means that it will be visible to programs we run from within this bash session. If you want that behavior too, just add back your export package_version in the if statement or below it.

Fair warning, I interpreted the prompt as though you wanted to run this actually from within an independent script, but I could be corrected. Also, I didn't understand the part about what you want to do with sqlite databases as different user profiles.

Craig H
  • 158
  • 8