Bash variable assignment failure/unary operator expected


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Bash variable assignment failure/unary operator expected
# 1  
Old 02-06-2018
Bash variable assignment failure/unary operator expected

I have a little code block (executing on AIX 7.1) that I cannot understand why the NOTFREE=0 does not appear to be assigned even though it goes through that block. This causes a unary operator issue.
Code:
#!/bin/bash
PLATFORM="AIX"
NEEDSPC=3000
set -x

if [ "${PLATFORM}" = "AIX" ]; then
    lsvg | grep -v rootvg | while read VGNAME
    do
        PPSTRG=$(lsvg ${VGNAME} | awk -F: '/PP SIZE/ {print $NF}')
        PPSIZE=$(echo ${PPSTRG} | awk '{print $1}')
        PPFREE=$(lsvg ${VGNAME} | awk -F: '/FREE PP/ {print $NF}' | awk '{print $1}')
        ((FREESPACE=${PPFREE}*${PPSIZE}))
        if [ ${FREESPACE} -gt ${NEEDSPC} ]; then
            printf "Sufficient free space for LV in ${VGNAME}\n"
            ((PPNEED=${NEEDSPC}/${PPSIZE}+1))
            NOTFREE=0
            break
        else
            printf "Insufficient space to create LV in ${VGNAME}\nFree space: ${FREESPACE} MB  Required: ${NEEDSPC} MB\nExpand ${VGNAME} and retry\n"
            NOTFREE=1
        fi
    done
    if [ ${NOTFREE} -eq 1 ]; then
        printf "nope\n"
        exit 64
    fi
else
    printf "Solaris\n"
fi
printf "NOTFREE: ${NOTFREE}\n"

yields:
Code:
prompt> ./dammit
+ '[' AIX = AIX ']'
+ lsvg
+ grep -v rootvg
+ read VGNAME
++ lsvg datavg
++ awk -F: '/PP SIZE/ {print $NF}'
+ PPSTRG='        256 megabyte(s)'
++ echo 256 'megabyte(s)'
++ awk '{print $1}'
+ PPSIZE=256
++ lsvg datavg
++ awk -F: '/FREE PP/ {print $NF}'
++ awk '{print $1}'
+ PPFREE=239
+ (( FREESPACE=239*256 ))
+ '[' 61184 -gt 3000 ']'
+ printf 'Sufficient free space for LV in datavg\n'
Sufficient free space for LV in datavg
+ NOTFREE=0
+ break
+ '[' -eq 1 ']'
./dammit: line 23: [: -eq: unary operator expected
+ printf 'NOTFREE: \n'
NOTFREE:

Yet if I strip out everything except the assignments and if blocks like:
Code:
#!/bin/bash
PLATFORM="AIX"
FREESPACE=4
NEEDSPC=3
set -x

if [ "${PLATFORM}" = "AIX" ]; then
    if [ ${FREESPACE} -gt ${NEEDSPC} ]; then
        NOTFREE=0
    else
        NOTFREE=1
    fi
    if [ ${NOTFREE} -eq 1 ]; then
        printf "nope\n"
    fi
fi
printf "NOTFREE: ${NOTFREE}\n"

The NOTFREE=0 assignment is made like:
Code:
prompt> ./test.sh
+ '[' AIX = AIX ']'
+ '[' 4 -gt 3 ']'
+ NOTFREE=0
+ '[' 0 -eq 1 ']'
+ printf 'NOTFREE: 0\n'
NOTFREE: 0

I'm being dragged, kicking and screaming, into bash from ksh due to SuSE gradually dropping ksh so I'm positive that I have some syntax issue going on but I have no idea what.


Also:
Code:
prompt> bash --version
GNU bash, version 4.2.50(1)-release (powerpc-ibm-aix6.1.2.0)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

# 2  
Old 02-06-2018
echo asdf | read X is a KSH habit that's unportable to other Bourne shells. Anything but KSH will set X in a subshell, where you'll never see it.

Some versions of BASH have a way to override this behavior, searching for it.

shopt -s lastpipe supposedly enables ksh like behavior but results are mixed for me.

Last edited by Corona688; 02-06-2018 at 04:10 PM..
This User Gave Thanks to Corona688 For This Post:
# 3  
Old 02-06-2018
Because the while block is fed by a pipe, it is run in a sub shell.
The sub shell inherits (gets copied) variables from the main shell, but not vice versa.
Only the ksh (and true derivatives- not mksh!) runs the last part of a pipe in the main shell.
So you can run your script with ksh.scriptname, or change the shebang to #!/bin/ksh.
If you want to stay with bash, you must recode your script.
This User Gave Thanks to MadeInGermany For This Post:
# 4  
Old 02-06-2018
Quote:
Originally Posted by port43
I have a little code block (executing on AIX 7.1) that I cannot understand why the NOTFREE=0 does not appear to be assigned even though it goes through that block. This causes a unary operator issue.
As others have stated the while loop is run in a subshell and variable assignments are lost the general accepted solution is to use Process Substitution eg:

Code:
    while read VGNAME
    do
        PPSTRG=$(lsvg ${VGNAME} | awk -F: '/PP SIZE/ {print $NF}')
        ...
    done < <(lsvg | grep -v rootvg)
    ...

This User Gave Thanks to Chubler_XL For This Post:
# 5  
Old 02-07-2018
Thank you all for clearing this up for me. Old habits die hard.
# 6  
Old 02-07-2018
Furthermore there is an additional problem: depending on the LV you may need more than one PP to increase the LV by 1 LP. These PPs may (depending on the setting of the "strictness" property) have to come from different PVs.

For instance, here is a (part of the) rootvg of one of my NIM-servers and the LV of the /usr filesystem:

Code:
nimserver:/root# lsvg -l rootvg
rootvg:
LV NAME             TYPE       LPs     PPs     PVs  LV STATE      MOUNT POINT
hd5                 boot       1       2       2    closed/syncd  N/A
hd6                 paging     4       8       2    open/syncd    N/A
hd8                 jfs2log    1       2       2    open/syncd    N/A
hd4                 jfs2       12      24      2    open/syncd    /
hd2                 jfs2       26      52      2    open/syncd    /usr
...

nimserver:/root# lsvg rootvg
VOLUME GROUP:       rootvg                   VG IDENTIFIER:  00f6476900004c000000015cd4205282
VG STATE:           active                   PP SIZE:        256 megabyte(s)
VG PERMISSION:      read/write               TOTAL PPs:      1022 (261632 megabytes)
MAX LVs:            256                      FREE PPs:       790 (202240 megabytes)
LVs:                19                       USED PPs:       232 (59392 megabytes)
OPEN LVs:           18                       QUORUM:         1 (Disabled)
TOTAL PVs:          2                        VG DESCRIPTORS: 3
STALE PVs:          0                        STALE PPs:      0
ACTIVE PVs:         2                        AUTO ON:        no
MAX PPs per VG:     32512                                     
MAX PPs per PV:     1016                     MAX PVs:        32
LTG size (Dynamic): 256 kilobyte(s)          AUTO SYNC:      no
HOT SPARE:          no                       BB POLICY:      relocatable 
PV RESTRICTION:     none                     INFINITE RETRY: no
DISK BLOCK SIZE:    512                      CRITICAL VG:    no
FS SYNC OPTION:     no                       CRITICAL PVs:   no

nimserver:/root# lslv hd2   
LOGICAL VOLUME:     hd2                    VOLUME GROUP:   rootvg
LV IDENTIFIER:      00f6476900004c000000015cd4205282.5 PERMISSION:     read/write
VG STATE:           active/complete        LV STATE:       opened/syncd
TYPE:               jfs2                   WRITE VERIFY:   off
MAX LPs:            32512                  PP SIZE:        256 megabyte(s)
COPIES:             2                      SCHED POLICY:   parallel
LPs:                26                     PPs:            52
STALE PPs:          0                      BB POLICY:      relocatable
INTER-POLICY:       minimum                RELOCATABLE:    yes
INTRA-POLICY:       center                 UPPER BOUND:    32
MOUNT POINT:        /usr                   LABEL:          /usr
MIRROR WRITE CONSISTENCY: on/ACTIVE                              
EACH LP COPY ON A SEPARATE PV ?: yes                                    
Serialize IO ?:     NO                                     
INFINITE RETRY:     no                     PREFERRED READ: 0

If i would increase the /usr filesystem by 256MB (=1LP) the VG must have at least 2 PPs free and they have to come from different disks because of the strictness setting (marked bold). Your script would test only for 256MB (=1PP) being free. For instance, in both of the following cases:

Code:
nimserver:/root# lsvg -p rootvg
rootvg:
PV_NAME           PV STATE          TOTAL PPs   FREE PPs    FREE DISTRIBUTION
hdisk1            active            511           1         1..0..0..0..0
hdisk2            active            511           0         0..0..0..0..0

nimserver:/root# lsvg -p rootvg
rootvg:
PV_NAME           PV STATE          TOTAL PPs   FREE PPs    FREE DISTRIBUTION
hdisk1            active            511          20         10..0..0..0..10
hdisk2            active            511           0         0..0..0..0..0

The increase would fail but your script would not anticipate this problem.

I hope this helps.

bakunin
This User Gave Thanks to bakunin For This Post:
# 7  
Old 02-07-2018
Thank you for taking the time to dissect that and notice it, bakunin. I was assuming a 1:1 and, well, assume...

In past positions I always tried to make sure everything was split/mirrored 1:1 to allow for the easiest replacement/fixing. I failed to consider that not all systems are as they should be. Smilie

I REALLY appreciate you pointing that out because it could have really bitten me in the ass.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Unary operator expected

In all my Googling, this usually happens when someone is comparing a variable, and that variable is unset. That doesn't appear to be the case for me... #!/bin/bash -x while read line do f=$(echo $line | tr -s ' ' | cut -d' ' -f 3) echo $f if then echo "This... (2 Replies)
Discussion started by: jnojr
2 Replies

2. UNIX for Dummies Questions & Answers

[: -gt: unary operator expected

Hi I have problem with my script. I dont now why but i don't change anything and script stop working. this is my code: #!/bin/sh for i in `ps -A | grep pocron.sh | grep -v grep | awk '{print $2}'` do COUNT=$((COUNT+1)) done ostatnie_wykonanie=`cat porader.log`... (1 Reply)
Discussion started by: fotex
1 Replies

3. UNIX for Dummies Questions & Answers

: unary operator expected

Hiya all, Why do I get a :unary operator expected when I try to put a condition statement in my shell script (sh) like so and how to fix? if ; then echo "say hello" else echo "don't say hello" fi ? It seems if the script receives an argument it works but if I don't put an... (4 Replies)
Discussion started by: cyberfrog
4 Replies

4. Shell Programming and Scripting

unary operator expected

i=0 while Shell script reports an error "unary operator expected" pointing the above line. $i by default is 0 and holds integer value and $buf is also holding integer value. Please can some one let me know what is missing. Thanks. (1 Reply)
Discussion started by: sunrexstar
1 Replies

5. UNIX for Dummies Questions & Answers

[: =: unary operator expected error

Why am I getting this error.... #!/bin/sh # iOS-Ad-Remover # Marshall Ford @ marshallbford@gmail.com # This project is hosted @ http://ios-ad- # remover.sourceforge.net # Under the GNU GPL open source license clear echo if ; then echo "You need to be root to run this script."; exit 0; #... (24 Replies)
Discussion started by: mbf123
24 Replies

6. Shell Programming and Scripting

line 5: [: -gt: unary operator expected

Hello all, :confused: I am not getting this error. Pls help me. ./construct_operon.sh: line 5: #!/bin/bash # Construct Operons using gene pairs. rm -rf operons_result lines=`awk 'END {print NR}' ecoli_operons` while ; do head -1 ecoli_operons | awk '{print $1"\n"$2}' > pattern ... (5 Replies)
Discussion started by: admax
5 Replies

7. Shell Programming and Scripting

unary operator expected

Im trying to fix my /etc/weekly that rotates various logs however it does them no matter what filesize they are and i want them to only do it if there file size exceeds 2M or something. So I'm playing with a script to get the filesize using a ls -l command which works and puts the value into a... (3 Replies)
Discussion started by: timgolding
3 Replies

8. UNIX for Dummies Questions & Answers

[: =: unary operator expected

HI, while running a script, I got the below mentioned error. /bin/sh: line10 : supportedMozillaVersion() { case "$*" in *rv:1.*) return 0;; *rv:.*) return 0;; *rv:*) return 1;; Mozilla\ 1.*) return 0;; Mozilla\ .*) return 0;; *) return 1;; esac } supportedFirefoxVersion() { case... (7 Replies)
Discussion started by: bhag281
7 Replies

9. Shell Programming and Scripting

unary operator expected

hi i am trying to compare a value with value 50. but i am getting " I am using if then echo "------------" fi please help thanks in advance Satya (2 Replies)
Discussion started by: Satyak
2 Replies

10. UNIX for Dummies Questions & Answers

unary operator expected error

Hi I am doing a script like if then echo "table name dosent exist" exit fi the problem is if $table_name is null then i am getting the error Please help me Thanks in advance (2 Replies)
Discussion started by: ssuresh1999
2 Replies
Login or Register to Ask a Question