Cannot get terminal application to launch with a graphical launcher when successful in terminal

I have been having an extremely annoying problem. For the record, I am relatively new at this. I've only been working with unix-based OS's for roughly two years, mostly Xubuntu and some Kali. I am pretty familiar with the BASH language, as that's the default shell for debian. Now, I've made this BASH script that works properly when it is accessed through the virtual console, xfce4-terminal 0.6.3. I've created a symbolic link in /bin to access the script from any directory, as most people do, I think. This is the script itself, designed to connect to WiFi access point from a CLI or virtual terminal.

 #!/bin/bash

 # WiFi Commander, a lazy way to lazily connect to the WiFi

 # Updated: 2-2-16, version 1.6

 # This script requires that nmcli, w3m, and w3m-img (if
 # you want to be able to see pictures), are all installed
 # on the computer running it


DDG="www.duckduckgo.com"

Cmdr () {
echo; echo "WiFi Command??"; echo
read command
}

test () {
echo; ping -c 1 $DDG
if [ "$?" -eq "0" ];
then echo; echo "Connection Successful."
else echo; echo "Connection Unsuccessful."
fi
}

interweb () {
echo; w3m $DDG
if [ "$?" -eq "0" ];
then echo " ";
else echo; echo "You are not connected to the internet."
fi
}

menu () {
echo; echo "Command Menu:"; echo
echo "S: Scan for WiFi"
echo "CTN: Connect to new WiFi"
echo "C: Connect to a Saved Connection"
echo "T: Test Connection"
echo "D: Disconnect from WiFi"
echo "VC: View Saved Connections"
echo "DelCon: Delete a Saved Connection"
echo "LB: Launch Browser (W3M)"
echo "SM: Show this Menu"
echo "E: Exit"
}

echo; echo "Welcome to WiFi Commander."; sleep .75

menu

while true; do

Cmdr

if [[ "$command" == S ]] || [[ "$command" == s ]];
then echo; echo $(iwlist scan | grep -E "Quality|Signal level|Encryption key|ESSID"; echo);
elif [[ "$command" == CTN ]] || [[ "$command" == ctn ]];
then echo; echo "SSID:"; echo; read ssid; echo; echo "Key:"; echo; read passwd; sudo nmcli d wifi connect "$ssid" password "$passwd" iface wlan0; echo
elif [[ "$command" == C ]] || [[ "$command" == c ]];
then echo; echo $(nmcli c); echo; echo "Connect to??"; echo; read ssid; nmcli c up id "$ssid";
elif [[ "$command" == T ]] || [[ "$command" == t ]];
then test
elif [[ "$command" == D ]] || [[ "$command" == d ]];
then nmcli d disconnect wlan0
elif [[ "$command" == VC ]] || [[ "$command" == vc ]];
then echo; echo $(nmcli c); echo
elif [[ "$command" == DelCon ]] || [[ "$command" == delcon ]];
then echo; echo $(nmcli c); echo; echo "Delete which??"; echo; read ssid; nmcli c delete id "$ssid";
elif [[ "$command" == LB ]] || [[ "$command" == lb ]];
then interweb
elif [[ "$command" == SM ]] || [[ "$command" == sm ]];
then menu
elif [[ "$command" == E ]] || [[ "$command" == e ]];
then echo; echo "Goodbye."; echo; exit
else echo; echo "Error: Command not recognised."
fi

done

This application when summoned via the symbolic link I've created for it, "w-cmdr", runs perfectly. But when I create a graphical launcher, the same kind that functions, say, an Internet browser, or a common application such as LibreOffice, it will not function. It executes the first actual command, which introduces the script and awaits the "command" from the script's "command menu" (as shown in the first picture). But anything actually entered into that menu results in a script failure, from which the only way to exit the script is CTRL+C. The failure is shown in the second picture.

What I don't understand is why it runs when originally executed by the CLI or virtual console, but when summoned by a graphical application launcher, which is configured to bring up a virtual console via the "run in terminal" option, as shown in the third picture, fails with no explanation. I use this script often, even when I'm using the GUI, and having a graphical launcher is honestly, not terribly important. But in enhances my laziness, which is the point of shell scripts haha. So please, someone help me. This is very frustrating. Any suggestions or ideas would be appreciated.

Whatever shell is running your script via the "run in terminal" command is a shell that doesn't know about the recent bash and ksh [[ expression ]] test syntax.

If you convert all occurrences of expressions of the form:

[[ "$command" == S ]] || [[ "$command" == s ]]

to:

[ "$command" = S ] || [ "$command" = s ]

or convert the entire if ... elif ... fi tree to a case statement:

case "$command" in
([Ss]) echo; echo $(iwlist scan | grep -E "Quality|Signal level|Encryption key|ESSID";;
([Cc][Tt][Nn]) echo; echo "SSID:"; echo; read said; echo; echo "Key:"; echo; read passwd; sudo nmcli d wifi connect "$ssid" password "$passwd" iface wlan0; echo;;
...
esac

then most shells based on Bourne shell syntax should be able to run your script.

However, note that naming a function test (overriding a utility normally found in /bin and the built-in found in most shells that accept Bourne shell syntax) is a VERY BAD idea.

Unless all of the utilities invoked by your script are found in /bin , you also need to set PATH to include a list of the directories containing those utilities.

1 Like

Thank you very much for your time and knowledge, the syntax error of the test statements were the problem. I'm just curious, what is the difference between:

[[ $variable == A ]]

and

[ $variable = A ]

I was taught to do the first when I first started to write scripting, and it's never given me any problems until this, which has now been fixed.

---------- Post updated at 03:43 AM ---------- Previous update was at 02:49 AM ----------

Also, using the "case" statement in this really made it way better. And I had never figured out how to properly use it until I saw what you wrote, so again, thank you. Showing me all of this has really improved my script and has given me more knowledge to equip me to write better scripts.

I think the script's shebang #!/bin/bash is malformed, so it doesn't use bash as the interpreter.

Did you consider bash 's select statement for your menu?

Could you please explain to me what BASH's "select" is?? I'm not familiar with this concept.

It's an easy way to dynamically build menus from a list of supplied words. c.f. man bash .

I hadn't noticed that the first line of your script contains a leading <space> character before the #!/bin/bash , so RudiC is probably correct in saying that that is why your script wasn't run using bash as its interpreter. Unless #!interpreter_path starts in column 1 on the 1st line in your file, that line is just a comment and has absolutely no effect on what interpreter will be used to run your script.

You haven't told us what operating system you're using, but it looks like the default shell on your is a Bourne shell or something like dash that doesn't include a lot of the bells and whistles provided by shells like bash and ksh that are extensions above and beyond what is required by the POSIX standards.

In POSIX-conforming shells the command:

[ expression ]

is a synonym for the command:

test expression

and there is no specification of what:

[[ expression ]]

does. The test and [ commands are utilities and they are often built-in into the shell as well as being available as stand-alone utilities. The [[ expression ]] is not a utility; it is a part of the syntax of those shells that provide this extension.

So, using [ "$var" = "string" ] is portable to a wide range of shells. And on shells that support [[ "$var" == "string" ]] , it is often a little bit faster, often supports more operators than test , and has different requirements for when double-quotes are required and how shell variables are expanded.

I'm glad my sample case statement helped you figure out how it works. We're here to help you learn how to use the tools that are available to you on UNIX, Linux, and similar systems.

There is a space before the shebang on the first line. The OS I'm using is Kali (the new Rolling version) which I believe by default uses Bourne again shell as the interpreter. Also, the way that I wrote the shebang with the space leading has always been how I've always written it. I didn't know that it made a difference for there to be a space?? But I'm new at this, also. And thank you for clarifying about the test statements, that was very helpful. So should the shebang not have a space in front of it?? If I were to use this script on a different OS that doesn't use bash, and that space were there before the shebang, would that different OS not know what interpreter to use?? Again, thank you for your time.

---------- Post updated at 04:48 PM ---------- Previous update was at 04:44 PM ----------

@ RudiC

I've been trying to implement the "select" statement in my script but it hasn't been very successful, as it is a very unfamiliar concept to me. But thank you for your time and idea, I'm sure if I fiddle around with it long enough, I'll get the hang of it haha.

I repeat: " Unless #!interpreter_path starts in column 1 on the 1st line in your file, that line is just a comment and has absolutely no effect on what interpreter will be used to run your script." A leading space makes a HUGE difference. Any attempt on any UNIX-like operating system to exec a shell script that does not have #! as the 1st two characters in that file will be run by that system's default shell.

If the #!/interpreter/path start in the 1st character of the 1st line of your file and the operating system doesn't find an executable file with that path, you're likely to get a cryptic message like:

-bash: script_file not found

(assuming that your login shell is bash and the name of the shell script you were trying to execute was named script_file ).

With the space there, another operating system (or your own) will know exactly what shell to use to invoke your script (that system's default) which will probably be named sh and might or might not be linked to bash , ksh , dash , ..., or a 1970's vintage pure Bourne shell depending on what operating system you are using at the time.

Of course, you can always use:

bash script_file

to have bash run script_file no matter what the first line of script_file looks like.

1 Like

@ RudiC

I tried to use the "select" statement for my script and couldn't figure out how to implement it correctly. But thank you for your time, I'm sure that if I keep messing around with it, I'll figure it out eventually haha.

---------- Post updated at 07:18 PM ---------- Previous update was at 07:12 PM ----------

@ Don Cragun

Thank you for clarifying the difference between the two "test" statements, it's really helped a lot. Also, I am aware of where my shebang is, and I have always had it like that in every script that I've ever written. The OS that I'm using is the Kali Rolling version, and I do believe that it's default interpreter is the Bourne again shell. I'm curious, does the space before the shebang really make a difference?? If I were to try and use this script in a different OS that does not use BASH as its default interpreter, would the script fail?? Does the space before the shebang, in that way, nullify the presence of that shebang??

Again, thank you for your time.

Please review post #9 in this thread!

Thank you for that clarification about the shebang. And also, please ignore the repeated replies over the same thing, I'm new to this website and am not very familiar with its nuances. I thought that the first time that I replied, it didn't go through.

Thank you for your time, you've really helped me a lot to have a better understanding of the BASH language and scripting in general.

select will take ANY list and turn it into a menu:

PS3="Enter Value X: "
select X in A B C D E F; do echo $X; done
1) A
2) B
3) C
4) D
5) E
6) F
Enter Value X:

Then, add a case ... esac construct ...

2 Likes

@ RudiC

Well, I've half successfully implemented the "select" statement in my script, but instead of actually doing the command, it just tells me the command linked to the number. The "case" statement functions fine in the version of this script before I added the "select" part.

Here is the script now:

#!/bin/bash

 # WiFi Commander, a lazy way to lazily connect to the WiFi

 # Unstable

 # This script requires that nmcli, w3m, and w3m-img (if
 # you want to be able to see pictures), are all installed
 # on the computer running it

DDG="www.duckduckgo.com"

test () {
echo; ping -c 1 $DDG
if [ "$?" -eq "0" ];
then echo; echo "Connection Successful."
else echo; echo "Connection Unsuccessful."
fi
}

discon () {
nmcli d disconnect wlan0
if [ "$?" -eq "10" ];
then echo; echo "wlan0 not found: Testing for wlan0mon...."; echo; sleep .75; discon2
fi
}

discon2 () {
nmcli d disconnect wlan0mon
if [ "$?" -eq "10" ];
then echo; echo "Error with the WiFi Adapter."
fi
}

interweb () {
echo; w3m $DDG
if [ "$?" -eq "0" ];
then echo " ";
else echo; echo "You are not connected to the internet."
fi
}

menu () {
echo; echo "Command Menu:"; echo
echo "S: Scan for WiFi"
echo "CTN: Connect to new WiFi"
echo "C: Connect to a Saved Connection"
echo "T: Test Connection"
echo "D: Disconnect from WiFi"
echo "VC: View Saved Connections"
echo "DelCon: Delete a Saved Connection"
echo "LB: Launch Browser (W3M)"
echo "SM: Show this Menu"
echo "E: Exit"
}

echo; echo "Welcome to WiFi Commander."; sleep .75; echo

PS3="WiFi Command: "
select command in "Scan for WiFi" "Connect to new WiFi" "Connect to a Saved Connection" "Test Connection" "Disconnect from WiFi" "View Saved Connections" "Delete a Saved Connection" "Launch Browser (W3M)" "Show this Menu" "Exit"; do echo $command; done
1) "Scan for WiFi"
2) "Connect to New WiFi"
3) "Connect to a Saved Connection"
4) "Test Connection"
5) "Disconnect from WiFi"
6) "View Saved Connection"
7) "Delete a Saved Connection"
8) "Launch Browser (W3M)"
9) "Show this Menu"
10) "Exit"
WiFi Command: 

case $command in

([1]) echo; echo $(iwlist scan | grep -E "Quality|Signal level|Encryption key|ESSID"); echo;;
([2]) echo; echo "SSID:"; echo; read ssid; echo; echo "Key:"; echo; read passwd; sudo nmcli d wifi connect "$ssid" password "$passwd"; echo;;
([3]) echo $(nmcli c); echo; echo "Connect to??"; echo; read ssid; nmcli c up id "$ssid";;
([4]) test;;
([5]) discon;;
([6]) echo; echo $(nmcli c); echo;;
([7]) echo; echo $(nmcli c); echo; echo "Delete which??"; echo; read ssid; nmcli c delete id "$ssid";;
([8]) interweb;;
([9]) menu;;
([10]) echo; echo "Goodbye."; echo; exit;;
*) echo; echo "Error: Command not recognised.";;

esac

The picture is of what happens when an option is entered into the script. As you can see, the command associated with the number from the "select" statement is not actually executed.

I'm not quite sure what is wrong with this, as the "select" statement is very new to me.

Once again, I thank you for your time.

The Picture of the "select" failure.

My above was just an example! Put your case ... esac in the place of the echo $x (which was a placeholder!).

1 Like

@ RudiC

Thank you for that clarification. Although it took me a good while to mess around with it, I finally figured out what I had wrong. Truly, a novice mistake haha. But I understand the "select" statement now, and it has helped improve the script, and will help me improve other scripts that I write. Again, thank you for your time and knowledge, they have both proved to invaluable.

For those who care, the new script, which is fully operational, is as follows below.

#!/bin/bash

 # WiFi Commander, a lazy way to lazily connect to the WiFi

 # Updated: 17-2-16, Version 2.3

 # This script requires that nmcli, w3m, and w3m-img (if
 # you want to be able to see pictures), are all installed
 # on the computer running it

 # You must be a sudoer or root to use this script

DDG="www.duckduckgo.com"

wa () {
sudo ifconfig | grep -Eow "wlan0"; sudo ifconfig wlan0 up
if [ "$?" -eq "0" ];
then echo; echo "wlan0 is present."; sudo ifconfig wlan0 up
else echo; echo "wlan0 is not present. Testing for wlan0mon...."; echo; sleep .75; wa2
fi
}

wa2 () {
sudo ifconfig | grep -Eow "wlan0mon"; sudo ifconfig wlan0mon up
if [ "$?" -eq "0" ];
then echo; echo "wlan0mon is present."; sudo ifconfig wlan0mon up
else echo; echo "No wireless devices are present."
fi
}

scan () {
echo; echo $(sudo iwlist scanning | grep -E "Quality|Signal level|Encryption key|ESSID"); echo
if [ "$?" -ne "0" ];
then echo; echo $(sudo iwlist scanning | grep -E "Quality|Signal level|Encryption key|ESSID"); echo
fi
}

test () {
echo; ping -c 1 $DDG
if [ "$?" -eq "0" ];
then echo; echo "Connection Successful."
else echo; echo "Connection Unsuccessful."
fi
}

discon () {
nmcli d disconnect wlan0
if [ "$?" -eq "10" ];
then echo; echo "wlan0 not found: Testing for wlan0mon...."; echo; sleep .75; discon2
fi
}

discon2 () {
nmcli d disconnect wlan0mon
if [ "$?" -eq "10" ];
then echo; echo "Error with the WiFi Adapter."
fi
}

interweb () {
echo; w3m $DDG
if [ "$?" -eq "0" ];
then echo " ";
else echo; echo "You are not connected to the internet."
fi
}


echo; echo "Welcome to WiFi Commander."; sleep .75; echo

PS3="WiFi Command: "
echo "Command Menu:"; echo; select command in "Activate Wireless device" "Scan for WiFi" "Connect to new WiFi" "Connect to a Saved Connection" "Test Connection" "Disconnect from WiFi" "View Saved Connections" "Delete a Saved Connection" "Launch Browser (W3M)" "Exit"
do
case $command in
"Activate Wireless device") wa;;
"Scan for WiFi") scan;;
"Connect to new WiFi") echo; echo "SSID:"; echo; read ssid; echo; echo "Key:"; echo; read passwd; sudo nmcli d wifi connect "$ssid" password "$passwd"; echo;;
"Connect to a Saved Connection") echo $(nmcli c); echo; echo "Connect to??"; echo; read ssid; nmcli c up id "$ssid";;
"Test Connection") test;;
"Disconnect from WiFi") discon;;
"View Saved Connections") echo; echo $(nmcli c); echo;;
"Delete a Saved Connection") echo; echo $(nmcli c); echo; echo "Delete which??"; echo; read ssid; nmcli c delete id "$ssid";;
"Launch Browser (W3M)") interweb;;
"Exit") echo; echo "Goodbye."; echo; exit;;
*) echo; echo "Command not recognised.";;
esac
echo; echo "Press Enter to view the Command Menu again."; echo
done