Avoid sourcing scripts multiple times

1,224

Solution 1

This morning I moved a bunch of personal information out of my bash_profile and bashrc and added them to a new file I call privaterc.

In my privaterc file I set this variable:

PRIVATERC_RUN=yes 

Now in my bash_profile I have added this line:

[[ $PRIVATERC_RUN != yes && -f ~/.privaterc ]] && source ~/.privaterc

This will cause privaterc to only be sourced if it hasn't previously been sourced in this shell.


Also as for the profile weirdness you are seeing, the article I linked in the comment states the following about mac:

Mac OS X — an exception

An exception to the terminal window guidelines is Mac OS X’s Terminal.app, which runs a login shell by default for each new terminal window, calling .bash_profile instead of .bashrc. Other GUI terminal emulators may do the same, but most tend not to.

Solution 2

I wonder it would be better to write a cliche in the sourced side, not sourcing side. (like C header files)

[[ "${_NAME_OF_THIS_LIBSCRIPT:-""}" == "yes" ]] && return 0
_NAME_OF_THIS_LIBSCRIPT=yes

With this, you do not need to repeat the same boiler plate every time you source a script file, which should contain something meant to be shared across multiple places. Or am I missing something? To be really honest, I am not a bash programming master, so I really would like to have insights from others.

Solution 3

Put a unique variable in the rc file - with a length of 1 or more bytes - then check if it has a length greater than 0 before sourcing bash_profile.

if [ ! X”” = X”$uniq_var” ] ; then . ~/.bash_profile ; fi

I just set bash as the login shell on MacOS, and didn’t have this problem. Perhaps they changed something again.

Share:
1,224

Related videos on Youtube

kalnic29
Author by

kalnic29

Updated on September 18, 2022

Comments

  • kalnic29
    kalnic29 over 1 year

    I'm trying to redirect user to the originally issued URL after authenticating them to our own oauth2 server. To do so I've read that it is possible to store data in the session object attached to the request. However I'm losing the data after the first redirect and consequently user are redirected to the fallback URL I provided.

    Here is the code that initialize the app

    const express = require('express');
    const bodyParser = require('body-parser');
    const cors = require('cors');
    const session = require('express-session');
    const cookieParser = require('cookie-parser');
    const auth = require('./auth');
    
    const app = express();
    const router = express.Router();
    
    app.use(cookieParser());
    app.use(bodyParser.urlencoded({ extended: true }));
    app.use(bodyParser.json());
    app.use(cors());
    app.use(session({
      secret: 'keyboard cat',
      cookie: {
       secure: true,
       maxAge: 36000000
      },
      resave: false,
      saveUninitialized: true
    }));
    
    auth.config(app);
    
    app.get('/', (req, res) => res.json({ message: 'root' }));
    app.get('/failure', (req, res) => res.json({ message: 'fail' }));
    
    // load all the routes
    require('../routes/posts')(router, auth);
    
    app.use('/api', router);
    app.use('/auth', auth.router);
    

    The auth module is as follows :

    const express = require('express');
    const passport = require('passport');
    
    const router = express.Router();
    
    module.exports = {
      config (app) {
        passport.serializeUser((user, done) => done(null, user));
        passport.deserializeUser((obj, done) => done(null, obj));
    
        passport.use(new OAuth2Strategy({
          authorizationURL,
          tokenURL,
          clientID,
          clientSecret,
          callbackURL
        },
        onAuthorize
        ));
    
        app.use(passport.initialize());
        app.use(passport.session());
    
        router.get('/uaa', passport.authenticate('oauth2'));
    
        router.get('/oauth/callback', passport.authenticate('oauth2'), (req, res) => {
            req.session.save(err => {
              if (err) throw err;
              res.redirect(req.session.redirectTo || '/');
            });
          });
      },
    
      ensureAuthenticated (req, res, next) {
        if (req.isAuthenticated()) return next();
        if (!req.session.redirectTo) req.session.redirectTo = req.originalUrl;
        req.session.save(err => {
          if (err) return next(err);
          res.redirect('/auth/uaa');
        });
      },
    
      router
    };
    

    And now if on the browser I request http://localhost:3333/api/questions (the matching route descrition is router.route('/questions').get(auth.ensureAuthenticated, PostController.questions.getAll)) I land in the ensureAuthenticated function which stores the initial route (/api/questions) but when I land in the final handler for my oauth2 callback, req.session.redirectTo does not exists. In fact it no longer exist right after the redirection to /auth/uaa.

    • Am I configuring something wrong ?
    • Are my router declarations okay ?
    • Why can't I access the data I previously stored ?

    Thank you.

    • Alexander Mills
      Alexander Mills about 6 years
      I don't understand why a terminal session is not just a subshell of a parent shell which has already inherited from /etc/profile or ~/.profile or whatever
    • jesse_b
      jesse_b about 6 years
      There is no problem sourcing .bashrc from .bash_profile and it is quite common in fact. Also related: joshstaiger.org/archives/2005/07/bash_profile_vs.html | Additionally please edit your question with additional thoughts/details instead of commenting.
    • Alexander Mills
      Alexander Mills about 6 years
      Yeah sourcing one file from another is not the answer here - that doesn't speed anything up - and one time I did that, I got an infinite loop when logging in, and I will never try that again :(
    • R. J. Mathar
      R. J. Mathar over 2 years
      To do things only once one may use a guarding if-statement in the style of if [[ $BASH_SUBSHELL -eq 0 ]] ; then .... fi
  • Yomo710
    Yomo710 almost 7 years
    Having this issue now. How'd you fix it?
  • kalnic29
    kalnic29 almost 7 years
    In my specific case, it as https related. So I removed the secure cookie option and it worked as expected after that.
  • Alexander Mills
    Alexander Mills about 6 years
    that might work, I will try it
  • Alexander Mills
    Alexander Mills about 6 years
    you think like me :) I also use "yes" instead of true/false
  • Alexander Mills
    Alexander Mills about 6 years
    yeah this doesn't work as I was hoping. Every time I open a new terminal window, it will resource the .privaterc file. That makes sense because when you call export it won't change the parent shell. So what we need is a way so that an original parent shell is what's called when we first login, and then any terminal will already be a subshell of that parent shell..
  • Alexander Mills
    Alexander Mills about 6 years
    How do you set bash as the login shell on MacOS?
  • Alexander Mills
    Alexander Mills about 6 years
  • Alexander Mills
    Alexander Mills about 6 years
    do you follow what I am saying? any other ideas? I have always found info on this stuff to be a little wishy washy, but there must be some way to inherit stuff in a bash shell, instead of having to re-source stuff every time.
  • user2497
    user2497 about 6 years
    @AlexanderMills I really liked Terminal.app, but I remember switching to iTerm2 after it got an overhaul - it was much more useful (tabswitching with CMD-{1,2,3,4,..} etc. 99% customizable. Try it if you can’t make Terminal.app behave.
  • Alexander Mills
    Alexander Mills about 6 years
    Yeah I use iterm2 most of the time. I also use the built-in terminal for Webstorm and VSCode even more. I need to get them all to behave.
  • Alexander Mills
    Alexander Mills about 6 years
    The good thing - all the terminals on my machine behave the same way. They source /etc/profile and ~/.bash_profile when they load.
  • user2497
    user2497 about 6 years
    @AlexanderMills What happens if you rename those files? Bootup doesn’t usually pull anything from /etc/profile
  • iamsaad
    iamsaad over 4 years
    This is not the best written bash, but the concept is valid! This is exactly what I was thinking, and it baffled me why others where using some crazy controls on the source loading side!
  • mx1up
    mx1up almost 4 years
    my idea exactly (although also a bash newbie). and it seems to work fine.. :)