0

I'm trying to write my first bash script to essentially install a bunch of dependencies and then execute a script.

I'm struggling debugging this with the user b/c I'm a dev which means I already have a bunch of tools installed (such as homebrew, ruby, node, etc) and my user has a fresh install of OSX. I want this script to work with all new users with fresh installs of OSX.

I am trying to export a bare bones PATH at the beginning of my script simply for debugging purposes to mimic the users fresh install.

My issue at hand is that I'm not sure how to actually reference node or npm specifically so that I can run npm install.

You can see what my echo's are producing. Any ideas how to properly install node/npm and then execute it?

#!/bin/bash
# Install necessary deps and runs script to create user for the DEV environment.
# Mainly used for non engineers to be able to create their own emails.

export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin::/usr/local
echo $PATH

# Install homebrew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

# Install node 8
/usr/local/bin/brew install node@8

# Install npm - https://stackoverflow.com/a/36631430/222403
/usr/local/bin/brew postinstall node@8

echo /usr/local/bin/brew --prefix node@8 = $(/usr/local/bin/brew --prefix node@8)
echo which node = $(which node) --> PRINTS which node =
echo which node@8 = $(which node@8) --> PRINTS which node@8 =
echo which npm = $(which npm) --> prints which npm =
....
  • Where are node and npm being installed? It could be that they are updating PATH during the installation process, but that change is not reflected in your script. If you know the install path, use the absolute path (as you have done for brew). You could also try re-sourcing your profile (source ~/.bash_profile, on Mac) as that is where any changes to a user's PATH would be made. – baum Jan 5 '19 at 4:06
  • 1
    If which can find a program, then it's in your path/environment, so you shouldn't need the full path anyway... (this may not be totally true but is generally) – baum Jan 7 '19 at 18:07
  • 1
    Try find /usr -name node ! – L. Levrel Jan 8 '19 at 19:47
  • 2
    Can you verify brew's exit status? – novice Jan 9 '19 at 0:03
  • 1
    As someone said, you should check exit status of brew commands. You can also add set -e under #!/bin/bash that will make bash exit when the first commands fails. Can you also replace which with type -a in your script? – Arkadiusz Drabczyk Jan 13 '19 at 14:16
1

Brew usually installs files into /usr/local/Cellar and symlinks them to /usr/local/bin.

The $PATH on these new boxes probably don't have /usr/local/bin in them. So you have two options:

  1. Read up on brew and anticipate where these packages are going to be installed, check the exit status for brew install ... and then hardcode the path to the new binaries / scripts that brew installs by changing you script to include absolute paths.

    If brew install foo worked then the foo binary should be available to invoke with /usr/local/bin/foo.

    This should give you a clue if brew install worked:

    /usr/local/bin/brew install node@8
    status=$(echo $?)
    if [[ "$status" -ne 0 ]]; then
        echo "Brew install node failed!"
        exit 1
    fi
    ...
    

    If you want to fully automate this script, check for errors when invoking commands, and handle them.

  2. Update your system path before your script tries to rely on it for command resolution. This should do the trick:

    #!/bin/bash
    export PATH="/usr/local/bin:$PATH"
    ...
    

    This does not rely on the user's bash env and should fix the which commands above. But consider, do your new boxes need /usr/local/bin in the $PATH anyway?

|improve this answer|||||
  • It's not /usr/local/Cellular but /usr/local/Cellar. – Arkadiusz Drabczyk Jan 13 '19 at 14:19
  • I'd say the second alternative is the simplest and most used. – CTodea Jan 14 '19 at 16:31
0

Assumption: I get the impression that once you've tried to install Node & NPM, you're trying to execute them without knowing the actual path to them in the script. This is what I'm basing my answer off of.


Calling Node & NPM:

This line should do the trick:

$(which <command>) <command arguments>

So for some NPM package you might use:

$(which npm) install <packagename>

This is because the full path of the executable (if listed before anything else in bash) is the thing that it's going to execute. The "$()" construct will literally substitute that executable location into bash.

Example:

$(which yes) IT WORKS!

Which will print out "IT WORKS!" on your screen repeatedly until interrupted.

As noted in the comments, if you know where Node & NPM will be installed to, then you can just use their full paths to execute them as well (though see the note for the slightly better way to do it).


(You're on your own if you need to install ruby, though I think you'd just do something similar to that "curl" line).


NOTE: You already have "/usr/local/bin" and "/usr/bin" in the $PATH variable in your script, so unless you have something wonky going on, you can run "ruby" and "brew" without specifying their full paths.

|improve this answer|||||
  • Read the whole script Catfish gave: which doesn't find node nor npm. – L. Levrel Jan 12 '19 at 10:42
  • That's not what I read, but an easy solution (in Linux, IDK about Mac) is to use the "locate" command to at least find out where the file is on your hard drive. Then, just use that path in the script. That could potentially have issues, but I'm assuming Apple is sane enough to have a standard installation procedure that a new user isn't going to mess with. – Mr. Minty Fresh Jan 14 '19 at 20:58
0

ADDED: How to find node.

I suggest that you should uninstall node@8 and re-install node@8 with --verbose option.

brew uninstall node@8
brew install --verbose node@8

It may show the steps of the installation. From the output, I hope you can find the location of node and its symbolic links.

Or,

You can find the paths of the installed files from node package with brew list command.

brew list node@8

It shows all the files installed.

And then, if you can use GNU find, it can find the symbolic link of a certain file.

find -L /dir/to/start/find -samefile /the/path/of/the/original/file

If you find the symbolic link of node which is made by brew, please add the path to $PATH. If no symbolic link exists, you should make symbolic link by yourself or should add the path for original node file.

The answer caused by misunderstanding the question: How to use which and variables

I assign the path into variable like this:

#!/bin/bash

NODE=`which node`
NPM=`which npm`

echo "Node.js path: ${NODE}"
$NODE -v

echo "npm path: ${NPM}"
$NPM -v

NOTE: `which node` is equal to $(which node). Backticks(backquotes) and $() returns the result.

which returns the full path of the command, so `which node` returns the path where node.js is installed. And it is assigned to $NODE variable.

|improve this answer|||||
  • Read the whole script Catfish gave: which doesn't find node nor npm. – L. Levrel Jan 12 '19 at 10:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.