Solved

Bash - Calling a function from another file. The other file includes another file. Having issues getting it to run.

Posted on 2016-09-12
10
134 Views
Last Modified: 2016-09-15
I have currently 20-25 tabs opened in chrome trying to figure this but, but it is probably because I am newish to bash and have only used it a little bit for some specific things. I am trying to make an appliation installed but am running in to some issues.

My first file is installer.sh which is basically just a menu, from that it calls singleinstall.sh, single install.sh has a good bit in it, the first bit below is the bit that pertains to my issue. There is a 3rd file that I want to contain all my functions called installfunctions.cfg , and then that 3rd file calls a 4th file called filecheck.cfg, which contains other functions for checking if files actually exist. If they do not exist, I want them to be installed (which I will get to that once I get this actual check working the way I want it).

 singleinstall.sh
#!/bin/bash
. installfunctions.cfg

testapp="nodejs"

echo "$(programcheck testapp)"
_npmInstalled=$(programcheck)
echo "Apps	$_npmInstalled"
^^^^ This is the way I tested it last, before that, I tested it as below : 

echo "$(programcheck testapp)"

Open in new window

The second file is installfunctions.cfg as seen below :
#!/bin/bash
#Installer functions
. filecheck.cfg

function programcheck(){
local _apps
_apps=$1
		for apps in $_apps; do
			if [[$(npm_package_is_installed $apps) == "1"]]; then
			echo -e "$apps is installed"
		else 
			echo " $apps Not installed"
fi
done
}

Open in new window

The above I have tried several ways, both with and without the (), having local and no local and just doing _apps=$1 alone, etc.

Below is part of the code for filecheck.cfg :
#!/bin/bash

function npm_package_is_installed {
  # set to 1 initially
  local return_=1
  # set to 0 if not found
  ls /home/store/node_modules | grep -w $1 >/dev/null 2>&1 || { local return_=0; }
  # return value
  echo "$return_"
}

Open in new window

Originally the code called for just npm_package_is_installed to call it from your main script (singleinstaller.sh) to look as follows :
"nodejs	   $(echo_if $(npm_package_is_installed nodejs))"

Open in new window

It would then also call a function within filecheck.cfg as below :
# display a message in red with a cross by it
# example
# echo echo_fail "No"
function echo_fail {
  # echo first argument in red
  printf "\e[31m? ${1}"
  # reset colours back to normal
  echo -e "\033[0m"
}

# display a message in green with a tick by it
# example
# echo echo_fail "Yes"
function echo_pass {
  # echo first argument in green
  printf "\e[32m? ${1}"
  # reset colours back to normal
  echo -e "\033[0m"
}

# echo pass or fail
# example
# echo echo_if 1 "Passed"
# echo echo_if 0 "Failed"
function echo_if {
  if [ $1 == 1 ]; then
    echo_pass $2
  else
    echo_fail $2
  fi
}

Open in new window

I am trying to use filecheck.cfg, mixed with my singleinstaller.sh as well as installfunctions.sh but keep getting the error as below :
installfunctions.cfg: line 20: [[0: command not found
 testapp Not installed
Apps

Open in new window

Which ends up being this lin below :
			if [[$(npm_package_is_installed $apps) == "1"]]; then

Open in new window

If anyone has some insight, I would greatly appreciate it!
0
Comment
Question by:MostHated
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 5
10 Comments
 
LVL 12

Accepted Solution

by:
tel2 earned 500 total points
ID: 41795401
What happens when you change line 20 in installfuctions.cfg from this:
    if [[$(npm_package_is_installed $apps) == "1"]]; then
to this:
    if [[ $(npm_package_is_installed $apps) == "1" ]]; then

Note: I've added 2 spaces.  One just inside each of the double brackets.
0
 
LVL 1

Assisted Solution

by:MostHated
MostHated earned 0 total points
ID: 41796037
It looks like the error went away at least. Though it is saying

testapp Not installed
Apps

Open in new window


At least with the error gone, it is a step in the right direction. I appreciate that. It is unfortunately those little things with spaces and what not that I am still trying to figure out and get used to, I am sure there are more that I have to look out for.

** Edit - Looks like I got it fixed!

In singleinstaller.sh, I changed

echo "$(programcheck testapp)"

Open in new window

to
echo "$(programcheck $testapp)"

Open in new window


Thank you  much for your help. I would never have realized I needed those space with the brackets.
0
 
LVL 12

Expert Comment

by:tel2
ID: 41796967
Thanks for the points, MostHated.

With your brains and my guesswork, we fixed this puppy.  Wot a team!

BTW, nice name.  How did you get to be called MostHated, anyway?

tel2
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Author Comment

by:MostHated
ID: 41798121
Appreciate the help. Definitely making good headway with my project now that I got over that hurdle, and now I make sure to read up and pay attention to the spacing in any examples I come across. : D I actually ended up changing it up even more as seen below.

Thanks, I actually earned the name back in my early days of playing MMO's, lol. I would camp people for hours on end until they would get so frustrated that they would make a character on my side just to message me to yell at me, one called me the most hated person alive, so I changed my name and camped him some more, lol. (It was mean of me, but I loved it. : P )

Here is part of how singleinstaller.sh currently looks
aptApps=("git" "mongodb" "npm" "ntp" "ntpdate")
npmApps=("nodejs" "parse-server" "express")
npmGlobalApps=("pm2")
testapp="nodejs"
installdir=/home/store/

# Create and move to installation directory
echo "$(createdirectory $installdir)"

# Get the latest package lists
#apt-get update  
echo "Checking if needed packages are installed. If missing, installing them"

# Call programing checking functions to see if prerequsites need to be installed
echo "$(programcheck ${aptApps[@]})"
cd $installdir
echo "$(npmprogramcheck ${npmApps[@]})"
cd $installdir
echo "$(npmglobalcheck ${npmGlobalApps[@]})"

Open in new window

and this is installfunctions.cfg
# Check if needed apt-get packages are installed, if not, install them.
function programcheck(){
_apps=("$@")
		for apps in "${_apps[@]}"; do
			if [[ $(program_is_installed $apps) == "1" ]]; then
			echo -e "$apps already installed"
		else 
			echo -e "$apps not found, installing."
			apt-get install -y $apps
fi
done
}

# Check if needed npm packages are installed, if not, install them.
function npmprogramcheck(){
_apps2=("$@")
		for apps2 in "${_apps2[@]}"; do
			if [[ $(npm_package_is_installed $apps2) == "1" ]]; then
			echo -e "$apps2 already installed"
		else 
			echo -e "$apps2 not found, installing."
			npm install $apps2
fi
done
}

# Check if needed npm global packages are installed, if not, install them.
function npmglobalcheck(){
_apps3=("$@")
		for apps3 in "${_apps3[@]}"; do
			if [[ $(npm_global_package_is_installed $apps3) == "1" ]]; then
			echo -e "$apps3 already installed"
		else 
			echo -e "$apps3 not found, installing."
			npm install -g $apps3
fi
done
}

Open in new window


It is working great. : )
0
 
LVL 12

Expert Comment

by:tel2
ID: 41798909
Good to hear it's working great, MH.

Now let's make it look a bit greater, for readability and simplicity.

You've got this kind of structure 3 times:

		for apps in "${_apps[@]}"; do
			if [[ $(program_is_installed $apps) == "1" ]]; then
			echo -e "$apps already installed"
		else 
			echo -e "$apps not found, installing."
			apt-get install -y $apps
fi
done

Open in new window


Firstly, the "echo" command's "-e" switch is to "enable interpretation of backslash escapes", so unless you've got any of those, you can remove it.

Your indentation looks unbalanced to me.  For example, your "fi" and "done" at the end are at the same indent level.  Everything inside the "for" should be indented, including the "fi".  How's this grab ya?:

	for apps in "${_apps[@]}"; do
		if [[ $(program_is_installed $apps) == "1" ]]; then
			echo "$apps already installed"
		else 
			echo "$apps not found, installing..."
			apt-get install -y $apps
		fi
	done

Open in new window

0
 
LVL 1

Author Comment

by:MostHated
ID: 41800453
I appreciate the input, I definitely agree on that. When I was writing this, I kept looking up examples on stackexchange and what not, they all had the code with fi and done like that with the rest indented. I kind of just thought it had to be that way due to the silly white space rules of bash, lol. I never thought to actually test it. >_< If it will not make a difference then I will definitely go and fix it all.
0
 
LVL 12

Expert Comment

by:tel2
ID: 41800676
You can have extra white space (almost) anywhere without stopping your code from working.  This includes tabs, spaces and newlines.

When I say "almost", there are exceptions like this:
    TESTAPP = 123   # Syntax error
    TESTAPP=123     # OK

The only language that I can think of that requires certain indentation is Python, and (I think) if you don't indent it correctly then it could have a different meaning (i.e. different logic).

Was there a good reason for using the "-e" switch with "echo"?
0
 
LVL 1

Author Comment

by:MostHated
ID: 41800693
The only reason I put that there was in some examples I was looking at, they had it there, lol. Anything weird you see about my code is mostly just because of what I saw people use / do in the 300 different searches and forum threads I have read through so far, and just kind of followed suit with their bad habits and such, because I just don't know the language well enough yet. I am working on it though. I did read that with Bash, it is that the white space does not matter until you hit the first actual character in the line, so you can tab or space all day, but once you hit a character, you have to start paying attention, so indentation is no issues. I can feel better now and go in and fix all the ugly parts, lol.

    I used to be real big into PHP back when I was younger, but then working for someone while programming made me hate it, so I went another route, but in the last year I have got back into it a lot, made a few games with the Unity game engine, have been learning more Javascript / NodeJS, and now doing the bash programming for a project a few friends and I are working on.

    They are professional programmers, so they just breeze through stuff, and I am a server / networking guy / IT Manager, so my skills are generally very well rounded, so there was not much for me to do on this project yet until we start looking in to scalability, hosting, things of that nature and I wanted to be useful. So I took on the task or making the installation script for our application. It is coming along really well and I am pleased with the results so far. : D

** Edit --

    I added some new functionality last night, and to my surprise, it worked the first try! I added to the main menu some user input to take in their desired username and password for the store and database, as well as their domain and email for the automatic letsencrypt functionality I am adding in, it then drops it in a temp file that I can then pick up and use later in the install process.
0
 
LVL 12

Expert Comment

by:tel2
ID: 41800707
OK.

Some of those things may not have been bad habits.  The use of "echo -e" may have been appropriate in the context of where you saw it used.

Note that white space doesn't always matter after the first non-white-space character, but you're right that it pays to pay more attention at that point.  For example, these are all valid (and do the same thing):
    let A=$A+1
    ((A=A+1))
    (( A = A + 1 ))

Where are you, anyway?  I'm in New Zealand.
0
 
LVL 1

Author Comment

by:MostHated
ID: 41800720
Ah, I see, I was meaning more the improper use of indentation, lol.  What made the spaces in the double brackets I had trouble with originally different than those examples above? I am in Tampa, FL, US. I have a pal I used to play WoW with who was in NZ, loved his accent, lol. Only thing he hated was the price of games there, and the speed / reliability of the internet a lot of the time. : /
0

Featured Post

Secure Your WordPress Site: 5 Essential Approaches

WordPress is the web's most popular CMS, but its dominance also makes it a target for attackers. Our eBook will show you how to:

Prevent costly exploits of core and plugin vulnerabilities
Repel automated attacks
Lock down your dashboard, secure your code, and protect your users

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The purpose of this article is to demonstrate how we can upgrade Python from version 2.7.6 to Python 2.7.10 on the Linux Mint operating system. I am using an Oracle Virtual Box where I have installed Linux Mint operating system version 17.2. Once yo…
Fine Tune your automatic Updates for Ubuntu / Debian
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
How to Install VMware Tools in Red Hat Enterprise Linux 6.4 (RHEL 6.4) Step-by-Step Tutorial

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question