LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 08-23-2018, 02:07 PM   #1
bluethundr
Member
 
Registered: Jun 2003
Location: Summit, NJ
Distribution: CentOS 5.4
Posts: 144

Rep: Reputation: 15
Post Call a function within a function in Bash Script


I have a very simple function that prints a banner when the work of the script is complete. This is all it does:

Code:
end_banner() {  
        echo "*********************************************"
        echo "*         Your work in AWS is done          *"
        echo "*********************************************"
    }
But when I call that function from the other functions in my script, it does not get invoked.

For example I try to call the end_banner function from this function:

Code:
create_instance() {
      ...lines that do stuff...
      end_banner
    }
And the output in the end_banner function does not get printed out. It doesn't even show up when I run the script with bash -x. It's like that end_banner line isn't even there.

Here's a minimal version of my entire script, with full versions of end_banner, create_volume and create_instance:


Code:
    end_banner() {
    echo "*********************************************"
    echo "*         Your work in AWS is done          *"
    echo "*********************************************"
    }

    main() {
      # 1 Lab
      if [ "$accountnumber" == 123456789 ]; then
         "$user_action"
         return
      fi
    
    }
    
    choose_account() {
      echo "1 Lab"
      echo "Please enter a number for the account you want to work in."
      printf "Choose AWS Account: "
      read -r aws_account_number
      echo
    # 1 Lab
    if [ "$aws_account_number" -eq 1 ]; then
         aws_account="Company Lab"
         aws_key="lab"
         accountnumber=123456789
         return
    fi
    }
    
    choose_action() {
      echo "These are the actions possible in AWS: "
      echo
      echo "5 Create Volume"
      echo "20 Create AWS Instance"
      echo; echo
      printf "Enter an action in AWS: "
      read -r action
      echo
      # 5 Create AWS Volume
      if [ "$action" -eq "5" ]; then
        user_action=create_volume
        return
      # 20 Create AWS Instance
      elif [ "$action" -eq "20" ]; then
        user_action=create_instance
        return
      fi
    
    }
     
    create_volume() { 
    echo "*   Create an EBS volume in AWS $aws_account  *"
    echo
    
     printf "Enter a volume name: "
     read -r volume_name
     echo
        # Lab
        if [ "$accountnumber" -eq 123456789 ]; then
        echo "Availability Zones for $aws_account"
        echo "AZ 1: us-east-1a"
        echo "AZ 2: us-east-1b"
        echo
        fi
    
        #Availability Zones
        printf "Enter availability zone\\nExample. Type out: us-east-1a\\n"
        printf "AZ: "
        read -r availability_zone
        echo
      
        # Volume Size
        printf "Enter size: "
        read -r volume_size
        echo
    
        # Create from snapshot
        printf "Create from snapshot (y/n): "
        read -r from_snapshot
        echo
        if [[ "$from_snapshot" = [Yy] ]]; then 
          printf "Enter Snapshot ID: "
    	    read -r snapshot_id
          echo
        else 
          printf "No Snapshot Required\\n\\n"
        fi
      
        # Add encryption
        printf "Encrypted (y/n): "
        read -r encrypted
        echo
        if [[ "$encrypted" = [Yy] ]]; then 
          printf "Enter KMS Key ID: "
    	    read -r kms_key_id
          echo
        else 
          printf "No Encryption Required\\n\\n"
        fi
      
        # Set the Owner / Application / Engagement
        printf "Enter the Owner Name: "
        read -r owner
        echo
        printf "Enter the application name: "
        read -r application
        echo
        printf "Enter the engagement code: "
        read -r engagement
        echo
       
      # Create the volume based on the above
    	if [[ "$from_snapshot" = [Yy] ]]; then 
    		#Create EBS Volume from Snapshot"
    		volume_id=$(aws ec2 create-volume --size "$volume_size" --availability-zone "$availability_zone"  --snapshot-id "$snapshot_id" --volume-type gp2  --tag-specifications "ResourceType=volume,Tags=[{Key=\"Name\",Value=\"$volume_name\"},{Key=Engagement,Value=\"$engagement\"},{Key=\"Owner\", Value=\"$owner\"},{Key=\"Application\", Value=\"$application\"}]" --profile="$aws_key" | jq -r '.VolumeId')
    		return
    	elif [[ "$encrypted" = [Yy] ]]; then
    		#Create EBS Volume with KMS Key"
    		volume_id=$(aws ec2 create-volume --size "$volume_size" --availability-zone "$availability_zone" --kms-key-id="$kms_key_id" --volume-type gp2  --tag-specifications "ResourceType=volume,Tags=[{Key=\"Name\",Value=\"$volume_name\"},{Key=\"Engagement\",Value=\"$engagement\"},{Key=\"Owner\", Value=\"$owner\"},{Key=\"Application\", Value=\"$application\"}]" --profile="$aws_key" | jq -r '.VolumeId')
    	elif [[ "$from_snapshot" = [Yy] && "$encrypted" = [Yy] ]]; then
    		#Create EBS Volume from snapshot with KMS Key"
    		volume_id=$(aws ec2 create-volume --size "$volume_size" --availability-zone "$availability_zone"  --snapshot-id "$snapshot_id" --volume-type gp2 --profile="$aws_key" --tag-specifications "ResourceType=volume,Tags=[{\"Key=Name,Value=\"$volume_name\"},{Key=\"Engagement\",Value=\"$engagement\"},{Key=\"Owner\", Value=\"$owner\"},{Key=\"Application\", Value=\"$application\"}]" --profile="$aws_key" |  jq -r '.VolumeId')
    	else
    		#Create a plain volume without snapshot and encryption
    		volume_id=$(aws ec2 create-volume --size "$volume_size" --availability-zone "$availability_zone" --volume-type gp2 --tag-specifications "ResourceType=volume,Tags=[{Key=\"Name\",Value=\"$volume_name\"},{Key=\"Engagement\",Value=\"$engagement\"},{Key=\"Owner\", Value=\"$owner\"},{Key=\"Application\", Value=\"$application\"}]" --profile="$aws_key" | jq -r '.VolumeId')
    	fi
      sleep 10
    	echo "Volume created is:  $volume_id"
      echo
      local VOLID=$1
      eval $VOLID="$volume_id"
     }
     
     
     
     create_instance() {
    
    
    echo "  Create An Instance in AWS $aws_account"
    
    
    printf "Enter Platform\\n"
    printf "Example: Windows / Linux\\n"
    printf "Plaform: "
    read -r platform
    
    # using LAB  amis for now
    if [ \( "$platform" = "Windows" \) ] || [ \( "$platform" = "windows" \) ]; then
      ami="ami-03bfe6d8e0e60051c"
    elif [ \( "$platform" = "Linux" \) ]  || [ \( "$platform"  = "linux" \) ]; then
      ami="ami-4fb38358"
    else
      printf "That is not a valid choice."
    fi
    
    printf "Enter an Instance Type: "
    read -r instance_type
    
    printf "Enter Number of Instances: "
    read -r num_instances
    
    printf "Enter a Subnet ID: "
    read -r subnet_id
    
    printf "Enter Security Group ID: "
    read -r security_group
    
    printf "Enter a key name: "
    read -r key_name
    
    printf "Enter a server name: "
    read -r name_tag
    
    printf "Enter an application name: "
    read -r application_tag
    
    printf "Enter an engagement code: "
    read -r engagement_tag
    
    printf "Enter an owner name: "
    read -r owner_tag
    
    printf "Enter a role: "
    read -r role_tag
    
    ## Launch the instance
    tag_instance_id=$(aws ec2 run-instances --count "$num_instances" --image-id "$ami" --instance-type "$instance_type" --key-name "$key_name" --subnet-id "$subnet_id" --security-group-ids "$security_group"  --profile="$aws_key" | jq -r '.Instances[].InstanceId')
    # Get volume ID and device name
    root_vol=$(aws ec2 describe-instances --instance-ids "$tag_instance_id" --profile="$aws_key" | jq -r '.Reservations[].Instances[].BlockDeviceMappings[].Ebs.VolumeId')
    root_vol_device_name=$(aws ec2 describe-volumes --volume-ids "$root_vol" --profile="$aws_key" | jq -r '.Volumes[].Attachments[].Device')
    az=$(aws ec2 describe-instances --instance-ids "$tag_instance_id" --profile="$aws_key" | jq -r '.Reservations[].Instances[].Placement.AvailabilityZone')
    
    echo
    printf "Instance ID: %s has been created in Availability Zone: %s\\n" "$tag_instance_id" "$az"
    printf "Wait till the instance is created to tag it.\\n"
    
    sleep 15
    
    # Tagging the new instance
    aws ec2 create-tags --resources "$tag_instance_id" --tags Key=Name,Value="$name_tag"  Key=Application,Value="$application_tag" Key=Engagement,Value="$engagement_tag" Key=Owner,Value="$owner_tag" Key=Role,Value="$role_tag" --profile="$aws_key"
    
    ## Tagging the Root Volume - fixed tags
    aws ec2 create-tags --resources "$root_vol" --tags Key=Name,Value="$name_tag root volume"  Key=DeviceName,Value="$root_vol_device_name" Key=Application,Value="$application_tag" Key=Engagement,Value="$engagement_tag" Key=Owner,Value="$owner_tag" Key=Role,Value="$role_tag" --profile="$aws_key"
    
    printf  "The instance %s now has the following tags:\\n" "$tag_instance_id"
    printf "Host Name: %s\\n" "$name_tag"
    printf "Application: %s\\n" "$application_tag"
    printf "Engagement: %s\\n" "$engagement_tag"
    printf "Owner: %s\\n" "$owner_tag"
    printf "Role: %s\\n" "$role_tag"
    
    echo
    printf "Do you need additional volumes (y/n): "
    read -r vol_answer
    if [[ "$vol_answer" = [Yy] ]]; then
      printf "Number of volumes to add: "
      read -r num_volumes
      volumes=()
      devices=( {f..z} )
      for (( i=0; i < num_volumes; i++ )); do
        CURID=''
        create_volume 'CURID'
        volumes[$i]=${CURID}
          printf "Attach volume ID: %s\\n" "${volumes[i]}"
          if [ \( "$platform" = "Windows" \) ] || [ \( "$platform" = "windows" \) ]; then
            device="/dev/sd${devices[i]}"
            aws ec2 attach-volume --volume-id "${volumes[i]}" --instance-id "$tag_instance_id" --device "$device" --profile="$aws_key" | jq '.'
            aws ec2 create-tags --resources "${volumes[i]}" --tags Key=Name,Value="$name_tag volume"  Key=DeviceName,Value="$device" Key=Application,Value="$application_tag" Key=Engagement,Value="$engagement_tag" Key=Owner,Value="$owner_tag" Key=Role,Value="$role_tag" --profile="$aws_key"
          elif [ \( "$platform" = "Linux" \) ]  || [ \( "$platform"  = "linux" \) ]; then
            device="/dev/xvd${devices[i]}"
            aws ec2 attach-volume --volume-id "${volumes[i]}" --instance-id "$tag_instance_id" --device "$device" --profile="$aws_key" | jq '.'
            aws ec2 create-tags --resources "${volumes[i]}" --tags Key=Name,Value="$name_tag volume"  Key=DeviceName,Value="$device" Key=Application,Value="$application_tag" Key=Engagement,Value="$engagement_tag" Key=Owner,Value="$owner_tag" Key=Role,Value="$role_tag" --profile="$aws_key"
          else
            printf "That is not a valid choice.\\n"
          fi  
      done
      return
    elif [[ "$vol_answer" = [Nn] ]]; then
      printf "Ok. No added volumes will be created.\\n"
    else
      printf "Input is incorrect.\\n"
    fi
    end_banner
    }
    
    choose_action
    choose_account
    main "$@"
What am I doing wrong?
 
Old 08-23-2018, 02:20 PM   #2
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,882
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
You're not doing anything wrong, that works for me.

Perhaps turn on debugging to determine what is happening.
 
Old 08-23-2018, 02:22 PM   #3
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,882
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
Code:
$ cat test.sh
end() {
    echo "1"
}

create() {
    echo "2"
    end
}

create
Output:
Code:
$ ./test
2
1
 
Old 08-23-2018, 03:08 PM   #4
bluethundr
Member
 
Registered: Jun 2003
Location: Summit, NJ
Distribution: CentOS 5.4
Posts: 144

Original Poster
Rep: Reputation: 15
I've found the culprit.

In this part of create_instances, I had a return that was causing the program to exit before the end_banner function was called:

Code:
for (( i=0; i < num_volumes; i++ )); do
        CURID=''
        create_volume 'CURID'
        volumes[$i]=${CURID}
          printf "Attach volume ID: %s\\n" "${volumes[i]}"
          if [ \( "$platform" = "Windows" \) ] || [ \( "$platform" = "windows" \) ]; then
            device="/dev/sd${devices[i]}"
            aws ec2 attach-volume --volume-id "${volumes[i]}" --instance-id "$tag_instance_id" --device "$device" --profile="$aws_key" 2>&1 | sed -e 's/An error occurred (InvalidVolume.ZoneMismatch) //g' | jq '.'
            aws ec2 create-tags --resources "${volumes[i]}" --tags Key=Name,Value="$name_tag volume"  Key=DeviceName,Value="$device" Key=Application,Value="$application_tag" Key=Engagement,Value="$engagement_tag" Key=Owner,Value="$owner_tag" Key=Role,Value="$role_tag" --profile="$aws_key"
          elif [ \( "$platform" = "Linux" \) ]  || [ \( "$platform"  = "linux" \) ]; then
            device="/dev/xvd${devices[i]}"
            aws ec2 attach-volume --volume-id "${volumes[i]}" --instance-id "$tag_instance_id" --device "$device" --profile="$aws_key" 2>&1 | sed -e 's/An error occurred (InvalidVolume.ZoneMismatch) //g' | jq '.'
            aws ec2 create-tags --resources "${volumes[i]}" --tags Key=Name,Value="$name_tag volume"  Key=DeviceName,Value="$device" Key=Application,Value="$application_tag" Key=Engagement,Value="$engagement_tag" Key=Owner,Value="$owner_tag" Key=Role,Value="$role_tag" --profile="$aws_key"
          else
            printf "That is not a valid choice.\\n"
          fi
      return 
      done
I removed that return line and the script now works as planned.
 
  


Reply

Tags
bash, bash function, bash scripting



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Bash Script Read Output of One Function In Another Function bluethundr Linux - Newbie 3 08-25-2018 07:45 AM
[SOLVED] read function call returning more amount of data than wiritten using write function chakka.lokesh Programming 1 09-11-2014 03:14 AM
[SOLVED] g++ error message no matching function for call to some function Jerry Mcguire Programming 6 04-13-2010 08:37 PM
[SOLVED] Threaded function cannot call a function with extern "C" but nonthreaded function can morty346 Programming 16 01-12-2010 05:00 PM
Compilation issue when Function is parameter in function call on LINUX sa20358 Linux - Software 2 07-24-2008 10:19 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 11:07 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration