What does VAR_NAME=${VAR_NAME:-"/some/path/file"} mean - bash

What does VAR_NAME=${VAR_NAME:-"/some/path/file"} mean in an shell script?
This is for an init script, I'm writing a custom one to get some of our startup operations into init scripts so that we can start them automatically on boot, but I don't have much experience with shell scripting so I'm using a startup script for an unrelated piece of software that's we've customized in the past.
The path pointed to is to a file that contains configuration values that override defaults set in the script.
I'm having trouble figuring out what that construct really means (the :- part in particular).
The script I'm working off of also seems to chain this operation together to resolve which value to use such as:
LOG_FILE=${LOG_FILE:-${LOGFILE:-$DEFAULT_LOG_FILE}}

${parameter:-word}
Use Default Values. If parameter is unset or null, the expansion
of word shall be substituted; otherwise, the value of parameter shall be
substituted.

It sets VAR_NAME equal to VAR_NAME if it exists or /some/path/file if it doesn't.
Chaining it would only make sense if the variable names were different going down the chain.

Related

What does set -a "Mark variables which are modified or created for export" actually mean?

The help text for set -a is somewhat cryptic to me, but maybe i just don't understand what bash is doing behind the scenes with variables. Can someone explain why "marking" variables is needed (what are "unmarked" variables)?
My bash man-page uses a slightly different wording for this: Each variable or function that is created or modified is given the export attribute and marked for export to the environment of subsequent commands. This sounds more clear to me. It means:
Each variable you define in your script, is placed in the environment of any child process you create, and each function you define is also available to each bash-child-process you create.

Setting up default overwritable constructors and destructors or other functions for a set of commands

alias cmd_name="source mainshell cmd_name"
My plan is to alias a single main script to a set of script names. Now on invocation of any script that main script would be called and it can define certain functions or constructors and destructor. Then it can check that script file if it has a constructor definition. If it has one, call that constructor else call the default one. Then source that script and then call the destructor. This would also give that script access to the default functions setup by main script. This shall work fine but these aliases can’t be exported to subshells.
To add to that, I just want these defaults functions available to that particular aliased set of commands and want those functions to destroy once command execution is complete. That’s why I can’t just write them on .bash_profile making it absolutely global.
command_name() {
# initial code
source path/to/command_name
# destructing code
}
Another option which I found was to create function for each name and call my script inside. This one is exportable too. In this way i could just encapsulate every command in a function with same name and can easily have initial codes and destroying code. Here the problem is that i can’t define any more functions inside that function and it would get really clumsy too doing everything inside a function.
Another thought I had was symbolic links, but they seem to have a limit to how many I can create to a particular script.
What should be the best way to achieve this or if its somehow an inappropriate design, can someone please explain?
IIUC you're trying to achieve the following:
A set of commands that necessarily take place in the context of the current shell rather than a new shell process.
These commands have a lot of common functionality that needs to be factored out of these commands.
The common functionality must not be accessible to the current shell.
In that case, the common code would be e.g. functions & variables that you have to explicitly unset after the command has been executed. Therefore, your best bet is to have a function per-command, have that function source the common code, and have the common code also have another function (called before you return) to unset everything.
Notes:
You can actually declare functions inside other functions, but the nested functions will actually be global - so name them uniquely and don't forget to unset them.
If they don't need to affect the current shell then you can just put them in their own file, source the common code, and not unset anything.
There is generally no limit to how many symlinks you can create to a single file. The limit on symlink chains (symlink to symlink to symlink etc.) is low.

How to Make Constants in an Expect Script?

I would like to be able to create and set the value of constants in an Expect script.
In scripts such as Bash and a great many programming languages, one can create and assign a value to a constant. I have tried many online sites looking how to do this in Expect, but I have surprisingly not been able to come across this basic information.
Creating and assigning a variable named name in Bash: name="Bob"
Creating and assigning a constant named CONFIG_FILE in Bash: readonly CONFIG_FILE="Configuration.ini"
Creating and assigning a variable named copyPath in Expect: set copyPath "/home/bob/tmp"
Creating and assigning a constant in Expect: ?????
How does one create and set the value of constants in an Expect script?
Like Python, TCL (the scripting language used for Expect) doesn't have constants.
I would suggest going the python route. Define them in all caps, don't change them and hope everyone else gets the hint.
set COPYPATH "/home/bob/tmp"
set PI 3.14159265359
If you really think you need them, there are some hacks in the link glenn jackman posted in the comments https://wiki.tcl-lang.org/page/constants.

Different approach for overriding variable at make launch

What is the best approach for overriding variable when launching make command?
make PREFIX="/new_path"
PREFIX="/new_path" make
I suspect that it's not exactly the same since in the first case the overriding is specified as a parameter of the make command, while in the second case (if I guess well) we use the shell definition for setting the variable then call the command make.
As you say, it depends on what you mean by "best". Both are appropriate in different circumstances.
By default makefile variable assignments take precedence over environment variable settings, and command line arguments override makefile variable assignments.
So, if you want to be sure the setting you give is used, then you should always use the command line: make PREFIX="new/path". If you want to provide a default value for a makefile to use if it doesn't already have a value, you should use the environment.

Make Variables from Parent Shell Script

In a makefile I'm reading, there are many references to a variable, projdir, defined and exported in the shell script that calls make; there are many instances of $(projdir) in the makefile.
From the make manual at http://www.gnu.org/software/make/manual/make.html#Reference, there are only two types of variables: recursively expanded variables and simply expanded variables. It seems projdir is neither one.
Question 1: Since the makefile works, it must be true that makefiles can access shell variables defined in the parent shell environment. Why is this not documented (or perhaps I did not find the correct documentation)?
Question 2: Unrelated to question 1, I see in Section 6.2 the line all:;echo $(foo). Why is the semicolon ; needed here?
Question 1. Environment variables automatically become make variables. This is explained in section 6.10:
Variables in make can come from the environment in which make is run. Every environment variable that make sees when it starts up is transformed into a make variable with the same name and value.
Question 2: Putting a semicolon after a rule name and optional prerequisites allows you to start the recipe on the same line. This is explained in section 4.2:
The first recipe line may appear on the line after the prerequisites, with a tab character, or may appear on the same line, with a semicolon.
They used this syntax in the example in 6.2 for brevity, so they could show the whole rule inline in the sentence; I think it's rarely used in practice.
From the make manual:
Variables in make can come from the environment in which make is run. Every environment variable that make sees when it starts up is transformed into a make variable with the same name and value.
As to your second question:
Why is the semicolon ; needed here?
Without the semicolon the right-hand side of : would specify the list of dependencies. The semicolon terminates that (empty) list.
Variables have both a flavor and an origin.
Expansion type is a flavor.
make contains a flavor function which can be used to find the type of variable in question. It will return one of undefined, recursive or simple.
Variables also have an origin which is where their value has come from. What you are seeing here is one of those possible origins.
The origin function will tell you the origin of a variable.
There are seven possible origins: undefined, default, environment, environment override, file, command line, override and automatic.
So your projdir variable has a flavor of simple and an origin of environment.

Resources