Running source command on parent shell from bash script - bash

I have a bash script where I make a few changes to the .bashrc. I then want to run the bashrc from my script so I've been running
source ~/.bashrc
to avoid having to reload my shell. The problem I've been seeing is that it's only being set in the subshell bash is running in.
Can I do anything from my script so that the source command is run in the parent shell?

What you could do, if you really wanted to: Provide a shell function which checks whether .bashrc has been modified, and if it is the case, sources this file. Let#s call this function check_reload. Then define your PS1 as
PS1='$(check_reload) .....'
With this setup, your .bashrc will be reloaded before you get a new command line.
While this should solve your problem, I personally would not do it: I consider the information in .bashrc fairly static, and I would not use a script to modify it, but do it manually with a text editor. But of course everyone can do this as he likes....

Related

Sourcing the same shell script file everytime

I just had a quick question regarding sourcing files in shell script.
I have created a shell script file that has a function which I can execute. However, everytime I restart my terminal and run the command in my shell I have to run source ~/path/to/shell/file everytime before running my function.
Is there any permanent fix for this?
Thank you!
This is what the shell startup files are for. If you're using bash, any commands you place in the file .bashrc in your home directory ($HOME/.bashrc) will be executed every time you start a new shell (the name is short for "bash run commands"). So either copy the file with your function definition into the .bashrc or just add the source command to it, and you should be good to go.

How to implicitly run a shell script sourced?

I have made a shell script to run as terminal command, but the cd commands inside it is not effective and hence I want to run it with source so that the cd commands take effect.
script name : "project.sh"
I added this file to /usr/local/bin, made it executable by chmod +x project.sh and it runs fine, but the cd command is not working.
I know it runs in a child process and hence at the end terminal returns back to the starting directory, rendering no effect of cd commands inside project.sh.
The solutions presented at Sol:1 do not work for me, because they asks me to run source <file>, which is not possible if I want to use it as Bash command.
You use the source command:
source /usr/local/bin/project.sh
There's no way to make this happen automatically by typing the script name, that always runs the script in a subprocess. If you don't want to have to type this all out, you could create an alias in your .bashrc to simplify it:
alias project='source /usr/local/bin/project.sh'
Then typing project will be translated to that full command.
Of course, source <file> is a Bash command - it uses the source builtin to run script <file> in the context of the current shell rather than in a child process, thus allowing commands in <file> to change the current shell's environment, such as in terms of the working directory (using cd).
Using source, or its alias ., is (ultimately) the only way to achieve that.
If your intent is not to have to invoke <script> explicitly with source, you have two options, both of which are best defined in your Bash profile, ~/.bash_profile (since you're on OS X; on Linux, use ~/.bashrc[1]):
I'll assume that your script is /path/to/foo, and that you want to invoke it sourced as just foo:
Option 1: Define an alias: alias foo='source "/path/to/foo"'
Option 2: Define a function: foo() { source "/path/to/foo"; }
Both aliases and functions execute in the current shell, allowing you to effectively hide the source call behind a single command; aliases are generally a little easier to define, but functions offer more flexibility.
By virtue of the alias / function being defined in your Bash profile, which itself is implicitly sourced, the commands in /path/to/foo will affect your interactive shells' environment.
Note: Either definition of foo will only be available in interactive shells (those that (automatically) source ~/.bash_profile).
Additional steps would be needed to make foo work inside non-sourced scripts as well, but at that point you should ask yourself whether you're obscuring things by not making the fact that /path/to/foo is getting sourced explicit.
If you're writing a script that must be sourced for distribution to others:
Install the sourcing command in the user's shell profile / initialization file (as described above) on installation of your script.
If there is no installation process (and also to enable on-demand installation in general), implement a command-line option for your script such as i (--install) that performs this installation on demand.
Preferably, also implement an uninstallation option.
Either way, build logic into the script so that it refuses to run when run without sourcing, and have the error message contain instructions on how to install sourcing.
See this answer for how to detect sourcing.
A real-world implementation of the above - although more elaborate due to being multi-shell - is my typex utility; source code here.
[1] On OS X, Bash instances started by Terminal.app are login shells, which means that the only (user-specific) file that is automatically sourced on startup is ~/.bash_profile.
By contrast, on most Linux systems Bash instances are non-login shells, where only ~/.bashrc is automatically sourced.
While it is common practice to source ~/.bashrc from one's ~/.bash_profile, this has to be configured manually and therefore cannot be relied upon blindly.

How do we persist a `source bash_profile` command outside of a ruby script?

What we're trying to do is call source bash_profile to reload a bash_profile file. The script grabs a person's bash_profile and load it onto a person's computer. The problem is that the source bash_profile won't persist outside the ruby script. After the script ends, the terminal looks the same as it did before. How can we make it so that source bash_profile persists outside the ruby script?
The bash_profile usually modifies the bash environment (installing functions, aliases, variables, readline bindings, etc.), and there is really no way to modify the environment of a parent bash process.
So the best you can do is end the ruby script by execing a new bash, specifying the -l (or --login) option to make it a login shell so that it will start by sourcing bash_profile. (You can also do this by making the first character of argument -, usually by setting it to -bash.)
If you have control over the way the ruby script is initiated, you might be able to cause it to be execed, in order that it replaces the parent bash process. That will make for a cleaner process tree.

source bash script automatically when new shell created

I have bash script within which some function are declared and I like to source it automatically when a new shell created so that I can use the functions immediately. Add a source ~/setsetup.sh in the ~/.bashrc seems do not work.
EDIT:
Both ~/.profile and ~/.bashrc works. I just have a stupid typo when source the script. Thanks!
If the new shell you create is a login shell, it will execute one of .bash_login, .bash_profile, or .profile (whichever it finds first) instead of .bashrc. Typically, you source .bashrc from one of the two bash specific ones if you use them. You should not put any bash-specific commands in .profile, as that file may be read by other non-bash shells. For example, if you decide to source your script from .profile, you should use the . setsetup.sh form, and make sure that nothing bash specific is in that script.
There are several files. The relevant one is likely ~/.profile for your case. It is often used to source .bashrc.
Check man .profile for details. When bash is started as login shell .profile is relevant, otherwise .bashrc.
What you are looking for is ~/.profile which should execute every time you create a new bash shell.

Why commands in .bashrc are not executed?

I have the following lines in my .bashrc which I would like to get executed upon logging in through ssh.
csh
source /x/y/.cshrc
source /x/y/z/sourceme
But the problem is that only the first command is being executed correctly.
(csh prompt is coming up)
The following source command is not effected.
I noticed that there are some errors which are thrown from bash (not csh) for the 'source' command
I read somewhere that this may be due to .bashrc getting executed multiple times. And source commands trying to get executed in bash itself rather than csh.
I want all the three commands to be executed one after other upon log-in. how can I do that? I tried .bash_profile .bash_login etc. Also I don't have write access to /etc/profile
The "commands" are interpreted by the bash shell. They aren't bytes to be fed to the terminal. What happens is that csh runs interactively, and once it exits bash will source the two (presumably csh) script files.
It looks like you're simply trying to change your shell to csh (why, I have no idea). Have you tried using chsh for that?
If you want to run these commands in csh, move them to your .cshrc.
A word of caution, though; using csh for absolutely anything raises the question, do you really think you know what you are doing? Why?
source is a "bashism", that is to say it won't work in other shells. Use . instead.

Resources