How to programmatically set a permanent environment variable in Linux? - linux

I am writing a little install script for some software. All it does is unpack a target tar, and then i want to permanently set some environment variables - principally the location of the unpacked libs and updating $PATH. Do I need to programmatically edit the .bashrc file, adding the appropriate entries to the end for example, or is there another way? What's standard practice?
Edit: The package includes a number of run scripts (20+) that all use these named environment variables, so I need to set them somehow (the variable names have been chosen such that a collision is extremely unlikely)

LSB-compliant (see spec) practice is to create a shell script in /etc/profile.d/ folder.
Name it after your application (and make sure that the name is unique), make sure that the name ends with .sh (you might want to add scripts for other shells as well) and export the variables you need in the script. All *.sh scripts from that directory are read at user login--the same time /etc/profile is sourced.
Note that this is not enforced by bash; rather, it's an agreement of sorts.

Standard practice is to install into directories already in the path and in the standard library directory, so there is no need to update these variables.
Updating .bashrc is a bit failure-prone, among other things; what if a user uses a different file or shell?

You can also generate and install a script that sets those variables. Users of your package then source that script or copy its contents to their own shell init file.

Related

How to ADD an environment variable that can be used by other process in Linux?

In a graphical DE, like KDE, what command can be used to add a new environment variable that can be used by any other process?
Note:
1) I'm aware of export A=B, but it only works for subsequent processes started in the same shell that executed the export, processes started else where, like a graphical application such as Chrome, won't be aware of the export.
2) I'm also aware that you can put it into ~/.bash_profile or alike, but that would need a restart/relogin for the setting to take effect.
Is there something like export but have effect for all applications and doesn't require a significant restart?
Your assumption that you need to restart after placing a variable definition (whether through an export statement or otherwise) in ~/.bash_profile, is flawed. You only need to source the file again after making modifications:
source ~/.bash_profile
or the more portable version:
. ~/.bash_profile
Either statement will (re)load any definitions in that file into your current shell. Sourcing is not the same as executing the script: it will modify the environment in the calling shell itself, not a subshell running the script.
A file like ~/.bash_profile may have many other definitions and settings in it that will mess with the shell. It is better to create a small (temporary) snippet with just the variables you want, and source that instead, as #JeremiahMegel suggests.
If you want to change the environment for a single process you run from the command line, you can set the variables on the same command line:
VAR=value /usr/bin/gedit
This will run gedit with the environment variable VAR set to value, but only for that one child process.
Unfortunately, your desktop applications are a bit more static than that. Most of the graphical applications you see in the menus are probably going to be represented by .desktop files in a folder like /usr/share/applications. These files are run in an environment that has almost none of the variables you are expecting. They rely on absolute paths, and most of the configuration is done by pointing the .desktop file to a script that performs its own setup. You can modify some of these files on an individual basis if you absolutely have to, but I would not recommend doing that. If you do insist on messing around with the graphical apps on your desktop, I would recommend making a copy of the desktop files you plan to modify in to ~/.local/share/applications, or whatever the equivalent is on your system. Those files will override anything found in /usr/share/applications and will only affect you.

Does anybody know where is LD_PRELOAD variable, in which file?

Just as the title said, I don't know where does this variable locate. I just know how to change it by typing:
$ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libXpm.so.4
Then is it possible to change it in its file?
LD_PRELOAD is an environment variable (part of the "environment" defined by the C library and Unix conventions). That specific variable tells the dynamic linker how to behave.
It is probably not set to anything by default. If you want to give it a default value every time you log in or start up a shell, you can put that export statement in your .profile or .bashrc file (or whatever the equivalent is for your shell of choice). There's probably also a place you could set it in /etc that would apply to all logins or shells started on your system (if you need it to be set for other users too).
If you only need to set it for a specific program though, that may be overkill. Instead, you might want to write a short shell script to set the environment variable up first, then launch the program. E.G.:
#!/bin/bash
export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libXpm.so.4
~/my_program_that_needs_a_special_library

Change root-path for bash auto-completition (TAB) feature

Can I force BASH to see certain folder (let's call it main_folder) as the root of my file-system? I need BASH to behave this way at least during auto-completion of parameter names and command names, while inside the folder.
Let's say that I have directory tree that looks like this:
/z/y/main_folder/a.txt
/z/y/main_folder/bin/b.txt
/z/y/main_folder/bin/c.txt
/z/y/main_folder/bin/d.sh
Now that I call this custom version of bash, I could simply type:
/> /bi(TAB)/(TAB) /a(TAB)
What would expand to:
/> /bin/d.sh /a.txt
Where d.sh is command to be run and a.txt is it's first parameter. If I was CDed into /bin/ I could do:
/bin/> ./(TAB) (TAB)(TAB)
What would expand the command d.sh, and would give three options for the first parameter (namely: b.txt, c.txt, d.sh).
Few brief additional points:
I do not care if the original root of the file-system is inaccessible or is accessible via hard/soft link.
I do not care if I am able to run any commands that are out of scope for main_folder (I will change the $PATH variable anyway) or any shell builtins.
I do not care what the $PS#, $PWD, etc. variables actually hold.
I do not want to make my own version of BASH (changing source-code). My application should (probably) be started via some script (sh) or program (C/C++/C#) that setups the environment and either continues in interactive mode or runs interactive shell on one of it's last lines.
I want to run this as an unprivileged user. I do not want to allow the user to chroot.
I am not concerned with security, and I am not intending to jail anyone. I simply need BASH to auto-complete.
I would not mind to 'trap' BASH during directory lookups.
I have a feeling that set, compgen, complete and compopt builtins are what I need to utilize, but I do not know how. It does not seem that the examples I have found about these commands show all the features, and man pages are quite chaotic.
Thanks, Kupto :)

What is PATH on a Mac (UNIX) system?

I'm trying to setup a project, storm from git:
https://github.com/nathanmarz/storm/wiki/Setting-up-development-environment
Download a Storm release , unpack it, and put the unpacked bin/ directory on your PATH
My question is: What does PATH mean? What exactly do they want me to do?
Sometimes I see some /bin/path, $PATH, or echo PATH.
Can someone explain the concept of PATH, so I can setup everything easily in the future without just blindly following the instructions?
PATH is a special environment variable in UNIX (and UNIX-like, e.g. GNU/Linux) systems, which is frequently used and manipulated by the shell (though other things can use it, as well).
There's a somewhat terse explanation on wikipedia, but basically it's used to define where to search for executable files (whether binaries, shell scripts, whatever).
You can find out what your current PATH is set to with a simple shell command:
: $; echo $PATH
(Note: the : $; is meant to represent your shell prompt; it may be something very different for you; just know that whatever your prompt is, that's what I'm representing with that string.)
Depending on your system and prior configuration, the value will vary, but a very simple example of the output might be something like:
/usr/bin:/bin:/usr/local/bin
This is a colon(:)-separated list of directories in which to search for executable files (things like ls, et cetera.) In short, when you try to execute a command from your shell (or from within some other program in certain ways), it will search through each of the directories in this list, in order, looking for an executable file of the name you're provided, and run the first one it finds. So that's the concept, per your question.
From there, what this documentation is telling you to do is to add the directory where you've unpacked the software, and in particular its bin subdirectory, into your $PATH variable. How to do this depends a bit on which shell you're using, but for most (Bourne-compatible) shells, you should be able to do something like this, if you're in the directory where that bin directory is:
: $; PATH="$PATH:$PWD/bin"; export PATH
In just about all but an actual Bourne shell, this can be shortened to:
: $; export PATH="$PATH:$PWD/bin"
(I won't bother explaining for CSH-compatible shells (because: I agree with other advice that you don't use them), but something similar can be done in them, as well, if that happens to be your environment of choice for some reason.)
Presumably, though, you'll want to save this to a shell-specific configuration file (could be ~/.profile, ~/.bashrc, ~/.zshrc... depending on your shell), and without reference to $PWD, but rather to whatever it expanded to. One way you might accomplish this would be to do something like this:
: $; echo "export PATH=\"\$PATH:$PWD/bin\""
and then copy/paste the resulting line into the appropriate configuration file.
Of course you could also generate the appropriate command in other ways, especially if your $PWD isn't currently where that bin directory is.
See also:
An article about $PATH (and more)
a related question on superuser.com

How to effectively organize scripts so they can be put under version control?

I have an ever growing list of scripts from simple one liners in bash to more complex python scripts.
Currently I source the one liners from a ~/.bash_functions file, while I put the more complex scripts into /usr/local/bin.
I would like to put all my scripts under version control so that they are easily portable to different machines.
Since not only my custom scripts reside under usr/local/bin, but also those of other appliactions, could I simply create a subdirectory, e.g. like this:
/usr/local/bin/scripts/
|-python
|-ruby
|-bash
and then just create a git repo out of said scripts folder?
Or is there a better, canonical way to actually organizing and versioning scripts?
I would install them in ~/bin and add that to your $PATH. You can then source control your bin directory as you wish.

Resources