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
82 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
  • 5
  • 5
10 Comments
 
LVL 11

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 11

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
 
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 11

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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
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 11

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 11

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

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Background Still having to process all these year-end "csv" files received from all these sources (including Government entities), sometimes we have the need to examine the contents due to data error, etc... As a "Unix" shop, our only readily …
How to remove superseded packages in windows w60 or w61 installation media (.wim) or online system to prevent unnecessary space. w60 means Windows Vista or Windows Server 2008. w61 means Windows 7 or Windows Server 2008 R2. There are various …
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
In a previous video, we went over how to export a DynamoDB table into Amazon S3.  In this video, we show how to load the export from S3 into a DynamoDB table.

760 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

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now