LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-16-2019, 01:18 PM   #1
anon033
Member
 
Registered: Mar 2019
Posts: 188

Rep: Reputation: 13
Output missing and [: =: unexpected operator in script


Hello everyone, I am trying to write a shell script that is in generic shel script NOT BASH. This shell script does one thing, mount drives. I got this idea from Luke Smith in this video he made: https://www.invidio.us/watch?v=YOpeXETS2z0, however I wanted something in generic script so I could use it on all my machines and something that did things a bit differently. After doing some research and reviewing how he did his I started on mine and wrote it out as I ran the commands in the shell. When I run the commands without variables and on their own everything works, but once I bring scripting into the picture it falls apart for some reason. I currently have this code

Code:
#!/bin/sh

# store all none mounted drives
drive=$(lsblk -lp | grep "part $" | awk '{print $1, "(" $4 ")"}')

if [ $drive = "" ]
then
	exit 0
fi

# ask which drive to mount
chosen=$(echo "$mountable" | dmenu -i -p "Mount which drive?" | awk '{print $1}')

if [ $chosen = "" ]
then
	exit 0
fi

# store mount directories in dirs
dirs=$(find /mnt/ /media/ -type d -maxdepth 3 2>/dev/null)

if [ $dirs = "" ]
then
	exit 0
fi

mountpoint=$(echo "$dirs" | dmenu -i -p "Type in mount Point.")

if [ $mountpoint = "" ]
then
dmenu -i -p "$mountpoint does not exist"
fi

# mount drive to mountpoint
sudo mount $chosen $mountpoint && notify-send "$chosen mounted to $mountpoint."
and when I run this script there are issue, for example after
Code:
drive=$(lsblk -lp | grep "part $" | awk '{print $1, "(" $4 ")"}')
runs there is no drives to pick from, but when I run that manually in the shell it shows my drive /dev/sdb1 as shown below
Code:
>>> lsblk -lp | grep "part $" | awk '{print $1, "(" $4 ")"}'
/dev/sdb1 (1.8G)
/dev/sdb2 (2.3M)
I am very confused why this is. I also get some syntax errors which if I am correct I shouldn't be getting. They are as follows

Code:
>>> ./mountd.sh 
./mountd.sh: 6: [: /dev/sdb1: unexpected operator
./mountd.sh: 14: [: =: unexpected operator
./mountd.sh: 22: [: /mnt/: unexpected operator
mount: /mnt/: can't find in /etc/fstab.
I apologize for posting once again here, I am just very new to shell scripting and honestly can't tell what the issue is. I did try to debug myself, but when I do everything works manually but not from a script. I want to fix these issues so I can add typing in sudo password to mount via dmenu then changing sudo to doas. Everything I can find through research is extremely BASH heavy and I honestly don't like shell specific scripts as it means it can't run on all my machines (OpenBSD has Ksh, Alpine has Ash and Mint has BASH).

#edit

It works now, I am dunce lol

Code:
chosen=$(echo "$mountable" | dmenu -i -p "Mount which drive?" | awk '{print $1}')
should be
Code:
chosen=$(echo "$drive" | dmenu -i -p "Mount which drive?" | awk '{print $1}')
still need to fix the issues with the '[' errors, but it works now

This has been solved, to see the solution for the '[' error there is a wonderful explanation below. The only other thing I can think of to ask here if anyone knows an equally efficient way to get the same info lsblk -lp gives using fdisk. I know I can use fdisk -l, but I also like the size info. If not that is fine, but I just like to test the tools I currently use for a task before adding a tool to my chain.

Last edited by anon033; 06-16-2019 at 02:23 PM.
 
Old 06-16-2019, 01:46 PM   #2
scasey
LQ Veteran
 
Registered: Feb 2013
Location: Tucson, AZ, USA
Distribution: CentOS 7.9.2009
Posts: 5,727

Rep: Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211
Couple of thoughts:
When you run from the command line, are you running as sh or bash?
Is set -x a bashism? Or will that work for sh scripts as well. If not, there's always the echo command to see what the script is seeing.
The error line number don't appear to line up with the script you've posted...that said, maybe quote the variables to control the interpolation of the contents?
And finally, I'm pretty sure all those OSs have a bash shell available...there's no requirement to use the "default" shell on any of them.
 
1 members found this post helpful.
Old 06-16-2019, 01:51 PM   #3
anon033
Member
 
Registered: Mar 2019
Posts: 188

Original Poster
Rep: Reputation: 13
Quote:
Originally Posted by scasey View Post
Couple of thoughts:
When you run from the command line, are you running as sh or bash?
Is set -x a bashism? Or will that work for sh scripts as well. If not, there's always the echo command to see what the script is seeing.
The error line number don't appear to line up with the script you've posted...that said, maybe quote the variables to control the interpolation of the contents?
And finally, I'm pretty sure all those OSs have a bash shell available...there's no requirement to use the "default" shell on any of them.
Oh, things like set -x aren't in my script that is all Luke's script. Mine only contains what I posted above, I did the ifs different to follow POSIX comp instead (for portability), this is running under sh not bash.

Last edited by anon033; 06-16-2019 at 01:53 PM.
 
Old 06-16-2019, 01:56 PM   #4
scasey
LQ Veteran
 
Registered: Feb 2013
Location: Tucson, AZ, USA
Distribution: CentOS 7.9.2009
Posts: 5,727

Rep: Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211
Quote:
Originally Posted by FOSSilized_Daemon View Post
Oh, things like set -x aren't in my script that is all Luke's script. Mine only contains what I posted above, I did the ifs different to follow POSIX comp instead (for portability), this is running under sh not bash.
I saw that. I'm asking if set -x is POSIX compliant (I don't know) and if it is, then put it in to help you debug the script.
If it's not, then add some debugging echo statements to see what's going on.

Just trying to help...I don't personally have a concern about portability. All the systems I work on are the same. Just luck, I guess.

Last edited by scasey; 06-16-2019 at 01:57 PM.
 
1 members found this post helpful.
Old 06-16-2019, 01:59 PM   #5
anon033
Member
 
Registered: Mar 2019
Posts: 188

Original Poster
Rep: Reputation: 13
Quote:
Originally Posted by scasey View Post
I saw that. I'm asking if set -x is POSIX compliant (I don't know) and if it is, then put it in to help you debug the script.
If it's not, then add some debugging echo statements to see what's going on.

Just trying to help...I don't personally have a concern about portability. All the systems I work on are the same. Just luck, I guess.
Ohhhh, my bad sorry about that. I'll check (as I don't know either) and use echos if not

set -x a is POSIX. I am stupid lol, when I was testing against Luke's verision I forget to use $drive not $mountable lol

Last edited by anon033; 06-16-2019 at 02:04 PM.
 
Old 06-16-2019, 02:11 PM   #6
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: Rocky Linux
Posts: 4,779

Rep: Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212
Quote:
Originally Posted by FOSSilized_Daemon View Post
Code:
#!/bin/sh

# store all none mounted drives
drive=$(lsblk -lp | grep "part $" | awk '{print $1, "(" $4 ")"}')

if [ $drive = "" ]
then
	exit 0
fi

# ask which drive to mount
chosen=$(echo "$mountable" | dmenu -i -p "Mount which drive?" | awk '{print $1}')

if [ $chosen = "" ]
then
	exit 0
fi

# store mount directories in dirs
dirs=$(find /mnt/ /media/ -type d -maxdepth 3 2>/dev/null)

if [ $dirs = "" ]
then
	exit 0
fi

mountpoint=$(echo "$dirs" | dmenu -i -p "Type in mount Point.")

if [ $mountpoint = "" ]
then
dmenu -i -p "$mountpoint does not exist"
fi

# mount drive to mountpoint
sudo mount $chosen $mountpoint && notify-send "$chosen mounted to $mountpoint."
Line 6: if [ $drive = "" ]
$drive needs to be quoted, otherwise this expands to
if [ xxxx xxxx xxxx xxxx = "" ]
and that has multiple arguments to the left of the "=".
You have similar problems with all if the 'if [ $xxx = "" ]' statements. Quotes are needed around the "$xxx" or else a null or multi-word value causes a syntax error.

Line 14: chosen=$(echo "$mountable" | dmenu -i -p "Mount which drive?" | awk '{print $1}')
The mountable variable has not yet been set. (I see you've fixed that)

Last edited by rknichols; 06-16-2019 at 02:12 PM. Reason: I see you've fixed ...
 
Old 06-16-2019, 02:20 PM   #7
anon033
Member
 
Registered: Mar 2019
Posts: 188

Original Poster
Rep: Reputation: 13
Quote:
Originally Posted by rknichols View Post
Line 6: if [ $drive = "" ]
$drive needs to be quoted, otherwise this expands to
if [ xxxx xxxx xxxx xxxx = "" ]
and that has multiple arguments to the left of the "=".
You have similar problems with all if the 'if [ $xxx = "" ]' statements. Quotes are needed around the "$xxx" or else a null or multi-word value causes a syntax error.

Line 14: chosen=$(echo "$mountable" | dmenu -i -p "Mount which drive?" | awk '{print $1}')
The mountable variable has not yet been set. (I see you've fixed that)
Ohhhh, that makes sense; thank you so much for taking the time to explain it out as well. All fixed now, thank you so much!
 
Old 06-16-2019, 03:00 PM   #8
anon033
Member
 
Registered: Mar 2019
Posts: 188

Original Poster
Rep: Reputation: 13
Quote:
Originally Posted by rknichols View Post
Line 6: if [ $drive = "" ]
$drive needs to be quoted, otherwise this expands to
if [ xxxx xxxx xxxx xxxx = "" ]
and that has multiple arguments to the left of the "=".
You have similar problems with all if the 'if [ $xxx = "" ]' statements. Quotes are needed around the "$xxx" or else a null or multi-word value causes a syntax error.

Line 14: chosen=$(echo "$mountable" | dmenu -i -p "Mount which drive?" | awk '{print $1}')
The mountable variable has not yet been set. (I see you've fixed that)
I hate to bug, but do you know how I would be able to put my password into dmenu and then have that be passed to sudo? In order to mount a drive I have to use sudo/doas and I would rather pass it via dmenu then disable a password for the account.
 
Old 06-16-2019, 03:23 PM   #9
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: Rocky Linux
Posts: 4,779

Rep: Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212Reputation: 2212
sudo reads the password directly from the TTY device and will not accept it from another source. That's to avoid unwise decisions like exposing your password in a script. I can't offhand think of a workaround that would not effectively allow passwordless mounting of any device on any directory.
 
Old 06-17-2019, 08:09 AM   #10
orbea
Senior Member
 
Registered: Feb 2015
Distribution: Slackware64-current
Posts: 1,950

Rep: Reputation: Disabled
I would suggest to add "set -eu" at the top of your script, where -e means it will exit on any error and -u means all unset variables are errors. I have learned that using this has improved the quality of my own scripts even if it is more work and should help in finding where in your code its failing.

You can check the posix spec here.

http://pubs.opengroup.org/onlinepubs...99/nframe.html

And the checkbashisms script from debian can help find issues with posix compliance.

https://sourceforge.net/projects/sla...eckbashisms.pl
https://packages.qa.debian.org/d/devscripts.html

However the only real good way of ensuring portability is to test many different shells, my current list of shells I test is ash, bash, dash, ksh, loksh, mksh, pdksh, posh, yash and zsh. Note that posh is inherently broken and zsh is not fully posix complaint, but is portable enough if extra care is taken.
 
Old 06-17-2019, 11:26 AM   #11
anon033
Member
 
Registered: Mar 2019
Posts: 188

Original Poster
Rep: Reputation: 13
Quote:
Originally Posted by orbea View Post
I would suggest to add "set -eu" at the top of your script, where -e means it will exit on any error and -u means all unset variables are errors. I have learned that using this has improved the quality of my own scripts even if it is more work and should help in finding where in your code its failing.

You can check the posix spec here.

http://pubs.opengroup.org/onlinepubs...99/nframe.html

And the checkbashisms script from debian can help find issues with posix compliance.

https://sourceforge.net/projects/sla...eckbashisms.pl
https://packages.qa.debian.org/d/devscripts.html

However the only real good way of ensuring portability is to test many different shells, my current list of shells I test is ash, bash, dash, ksh, loksh, mksh, pdksh, posh, yash and zsh. Note that posh is inherently broken and zsh is not fully posix complaint, but is portable enough if extra care is taken.
Question, do you know how I would clear all the variables once this script finishes? I have found a way to do sudo via dmenu, but don't want to keep my password in a variable for security reasons.
 
Old 06-17-2019, 12:22 PM   #12
orbea
Senior Member
 
Registered: Feb 2015
Distribution: Slackware64-current
Posts: 1,950

Rep: Reputation: Disabled
After a script finishes any variables you set during the script will be gone. If you want to clear a variable before the script finishes you can always either overwrite it by setting it to a new value, turn it into a blank variable or unset it. Note that blank and unset variables are not the same thing.

Code:
# blank variables
foo=
bar=''

# unset variables
unset foo bar
If you want to set variables in your current environment from a script you have to source it instead of executing it.

Code:
# sourcing scripts
# note that using 'source' is not portable while using '.' is
. foo.sh
. bar.sh

# executing scripts
./foo.sh
sh foo.sh
From looking at your script I am failing to see where you password is being stored in a variable, when you type your password for sudo its not being recorded anywhere (Assuming no keylogger of course).

Last edited by orbea; 06-17-2019 at 12:25 PM.
 
  


Reply



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
LXer: IBM's Red Hat Deal, NuoDB Operator Now Has Red Hat OpenShift Operator Certification, Krita 4.2.0 Alpha Released, Elive 3.0 Update, UBp LXer Syndicated Linux News 0 05-09-2019 06:21 PM
[SOLVED] Bash script unexpected operator postcd Linux - Newbie 6 03-10-2014 07:08 AM
[SOLVED] C++ Operator Overloading Within an Already Overloaded Operator mirlin510 Programming 8 04-17-2011 12:02 PM
unexpected operator/operand in Bourne script ocicat Programming 4 07-28-2007 05:44 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:06 PM.

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