Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sourcing .bashrc #1

Closed
maximilianschmitt opened this issue Jul 26, 2015 · 15 comments
Closed

sourcing .bashrc #1

maximilianschmitt opened this issue Jul 26, 2015 · 15 comments

Comments

@maximilianschmitt
Copy link

@maximilianschmitt maximilianschmitt commented Jul 26, 2015

Hi, I'm trying to use n-install in a Vagrant provisioning script. It tells me to

IMPORTANT: OPEN A NEW TERMINAL WINDOW before using n and Nodejs/io.js.

but I thought I could just

source $HOME/.bashrc

instead.

I'm using an ubuntu/precise64 box and n-install IS appending the necessary lines for n to the $HOME/.bashrc file. However, these three lines

curl -L http://git.io/n-install | bash -s -- -y io:latest
source $HOME/.bashrc

npm i pm2 knex babel gulp -g

produce the following error message:

==> default:    installed : v2.4.0
==> default: === n successfully installed.
==> default:   The active Node.js/io.js version is: v2.4.0
==> default:   Run `n -h` for help.
==> default:   To update n later, run `n-update`.
==> default:   To uninstall, run `n-uninstall`.
==> default:
==> default:   IMPORTANT: OPEN A NEW TERMINAL WINDOW before using n and Nodejs/io.js.
==> default: ===
==> default: /tmp/vagrant-shell: line 19: npm: command not found

If I vagrant ssh and look at $HOME/.bashrc, it contains the following line

export N_PREFIX="$HOME/n"; [[ :$PATH: == *":$N_PREFIX/bin:"* ]] || PATH+=":$N_PREFIX/bin"  # Added by n-install (see http://git.io/n-install-repo).

and n/node/npm work fine:

vagrant@webapp:/vagrant$ n --version
2.0.0
vagrant@webapp:/vagrant$ node -v
v2.4.0
vagrant@webapp:/vagrant$ npm -v
2.13.0

Is there another file that needs to be sourced so I can use n/node/npm without opening a new terminal window?

Thanks for your help!

@mklement0

This comment has been minimized.

Copy link
Owner

@mklement0 mklement0 commented Jul 26, 2015

@maximilianschmitt:

That's curious. On a Linux box with Bash as the current user's shell, source $HOME/.bashrc should indeed work, assuming all your 3 lines are run in the same script.

However, I know nothing about Vagrant - what extra considerations come into play?

As a - suboptimal - workaround, you can omit the source $HOME/.bashrc line and amend the npm i ... line as follows:

 N_PREFIX="$HOME/n" PATH="$HOME/n/bin:$PATH" npm i pm2 knex babel gulp -g

This hard-codes what source $HOME/.bashrc is meant to do into the npm installation command.

But I'd definitely like to understand why your approach didn't work.

@maximilianschmitt

This comment has been minimized.

Copy link
Author

@maximilianschmitt maximilianschmitt commented Jul 27, 2015

Hey! Thanks, your workaround definitely works. After searching around a bit more I found out that the my .bashrc contains this line at the top by default:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

So I guess the .bashrc never gets sourced completely. Do you have an idea what else might be a good solution that isn't a workaround that could break in the future?

Thanks for your help!

@mklement0

This comment has been minimized.

Copy link
Owner

@mklement0 mklement0 commented Jul 27, 2015

@maximilianschmitt: I suggest simply removing your check for interactivity from your .bashrc: there's no need for such a check, because Bash itself makes sure to only automatically source this file in interactive shells.
(Applies to Ksh and Zsh analogously.)

@mklement0 mklement0 closed this Jul 27, 2015
@mklement0

This comment has been minimized.

Copy link
Owner

@mklement0 mklement0 commented Jul 27, 2015

@maximilianschmitt: I've updated n-install to mention sourcing the (shell-specific) initialization file as an alternative to opening a new terminal window on successful installation; e.g.:

IMPORTANT: OPEN A NEW TERMINAL TAB/WINDOW or run `. ~/.bashrc`
           before using n and Nodejs/io.js.
@maximilianschmitt

This comment has been minimized.

Copy link
Author

@maximilianschmitt maximilianschmitt commented Jul 31, 2015

Thanks for looking into it. In the end I decided to 'manually' install n because I feel like it is safer than automatically modifying defaults in the bashrc.

@mklement0

This comment has been minimized.

Copy link
Owner

@mklement0 mklement0 commented Jul 31, 2015

@maximilianschmitt:

I understand that concern. Modifying shell-initialization files is often poorly implemented.

However, n-install tries hard to do the right thing: it'll only modify its own entry, it'll abort if it finds a "foreign" definition of N_PREFIX, and it preserves the file's inode, which ensures that if the init file happens to be a symlink, it is preserved.

If you're up for it, I encourage you to give it a shot and report any problems - hopefully, there'll be none.

@maximilianschmitt

This comment has been minimized.

Copy link
Author

@maximilianschmitt maximilianschmitt commented Jul 31, 2015

Oh no my concerns aren't at all with n-install, they are purely with ME modifying the .bashrc. to remove this line:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

It's just simpler to install n from scratch in that case.

@mklement0

This comment has been minimized.

Copy link
Owner

@mklement0 mklement0 commented Jul 31, 2015

I see. Given that Bash itself ensures that ~/.bashrc is only read in interactive shells, in what scenarios do you need this line?

@mklement0

This comment has been minimized.

Copy link
Owner

@mklement0 mklement0 commented Aug 5, 2015

@maximilianschmitt:

I'm genuinely curious: I've personally never used [ -z "$PS1" ] && return in my Bash/Ksh/Zsh initialization files, for the reason stated (the shells themselves ensure that ~/.bashrc, ~/.kshrc, ~/.zshrc are only sourced on startup in interactive shells).

I'm wondering if I'm missing something, so please tell me why and under what circumstances it is needed.

Conversely, you've experienced the downside of including this statement: it generally gets in the way of on-demand reloading of an updated initialization file for making changes take effect in the current shell.

@maximilianschmitt

This comment has been minimized.

Copy link
Author

@maximilianschmitt maximilianschmitt commented Aug 5, 2015

Hey @mklement0, sorry I missed your last response. I did not include this line in the .bashrc, it was there by default. You can see for yourself if you boot a ubuntu/precise64 or ubuntu/trusty64 box with Vagrant. So yeah, I have no idea why this line is included or what it is good for to be honest.

@mklement0

This comment has been minimized.

Copy link
Owner

@mklement0 mklement0 commented Aug 6, 2015

@maximilianschmitt:

Thanks; I took a closer look and found that, sadly, even a stock Debian/Ubuntu installation preinstalls a ~/.bashrc with that line in place.

I believe this is misguided, and, among the platforms I looked at - OSX, Fedora/CentOS, PC-BSD, Debian/Ubuntu - Debian/Ubuntu platforms are the only ones that do that in ~/.bashrc.

The others either do not come with default ~/.bashrc files or, if they do, that line is not present.

While the others in part also have such a statement at the system level (e.g., /etc/bash.bashrc), that less likely to be a problem, as the system-wide initialization files aren't typically re-sourced.

Fedora/CentOS (and thus presumably RHEL) get it right: even in the system-wide initialization file they do not categorically exit in non-interactive shells, but enclose terminal-relevant commands in a if [ "$PS1" ] … statement. And I'm not even sure that that is strictly necessary, as executing these commands in a non-interactive shell is usually benign.

Here's a - suboptimal - workaround, which simply filters out the interactivity check:

eval "$(grep -vFx '[ -z "$PS1" ] && return' $HOME/.bashrc)"

This can be used in lieu of source $HOME/.bashrc (and is no more unsafe than that).

Obviously, anticipating and filtering out all variations of such a check would be more difficult.

As an alternative workaround - still not great - you could invoke your entire installation script in a simulated interactive shell:

 bash --norc --noprofile -i <yourInstallScript>

-i treats the shell as interactive, while --norc and --noprofile suppress sourcing the profile/initialization scripts on startup.

@maximilianschmitt

This comment has been minimized.

Copy link
Author

@maximilianschmitt maximilianschmitt commented Aug 9, 2015

Awesome of you to try and get this to work. I do have to be honest: currently a manual installation of n is easier for me in Vagrant provision scripts. I think this might be helpful to other users though, so maybe add it to the README?

@mklement0

This comment has been minimized.

Copy link
Owner

@mklement0 mklement0 commented Aug 9, 2015

@maximilianschmitt Understood; re README: good idea, thanks - I just did.

@stefanmaric

This comment has been minimized.

Copy link
Contributor

@stefanmaric stefanmaric commented Nov 23, 2015

I was having this very same issue with Vagrant + Ubuntu image.

I found out that simply setting the shell to interactive mode directly into the provision file before sourcing .bashrc would prevent the issue, so:

set -i
source ~/.bashrc
# and turn it off to prevent side effects
set +i
# your node/npm/n/gulp/bower/etc commands here

@mklement0 : maybe you want to reflect this workaround in the README.

@mklement0

This comment has been minimized.

Copy link
Owner

@mklement0 mklement0 commented Nov 24, 2015

@stefanmaric: Excellent tip, thank you - I've updated README.md accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.