I am having an issue getting BASH to update a variable in a piece of scripting that I am working on. Below is an excerpt from my script that I have having troubles with
read -p "Did you plan on running the server from a Ramdisk?(y/n)" RAMDISK
if [[ "$RAMDISK" == [yY] ]]; then
read -p "What is the full path to where you would like to create the ramdisk?(/var/RAMDISK)" RAMDIR
read -p "How big did you want the ramdisk to be?(2048)" RAMSIZE
if [[ "$RAMSIZE" -lt 1024 ]]; then
$NEWRAMSIZE = $((RAMSIZE*1024)) #FIXME
echo $NEWRAMSIZE
fi
RAMDISK="Enabled"
fi
if [[ "$RAMDISK" == [nN] ]]; then
RAMDISK="Disabled"
fi
echo $NEWRAMSIZE
My problem is that no matter what I am trying, the RAMSIZE variable never gets multiplied by 1024. I am trying to make it so no matter what number you enter, it will always get changed to a size in mb instead of gb, assuming anything less than 1024 is a gb size. Earlier in the script RAMSIZE defaults to 2048 and it never seems to be changed during the if statement. Please help?
I see three problems: you shouldn't have spaces around the = in an assignment, you shouldn't use $ on the variable you're assigning to ($variable is how you get the value of a variable, not how you set it), and you're using RAMSIZE in some places and NEWRAMSIZE in others. The critical lines are:
if [[ "$RAMSIZE" -lt 1024 ]]; then
RAMSIZE=$((RAMSIZE*1024)) # Note: no spaces, no extra $, same variable
echo $NEWRAMSIZE
fi
...
echo "$RAMSIZE" # Same variable
BTW, you can use shellcheck.net to spot basic problems like this.
Related
During a scripting challenge, it was asked to me to decode X times (saying 100) a base64 files (base64.txt).
So I wrote this small bash script to do so.
for item in `cat base64.txt`;do
for count in {1..100};do
if [ $count -eq 1 ]; then
current=$(echo "$item" |base64 --decode)
else
current=$(echo "$current" |base64 --decode)
fi
if [ $count -eq 100 ]; then
echo $current
fi
done
done
It is working as expected, and I got the attended result.
What I am looking for now, is a way to improve this script, because I am far to be a specialist, and want to see what could improve the way I approach this kind of challenge.
Could some of you please give me some advice ?
decode X times (saying 100) a base64 file (base64.txt)
there is only 1 file, that contains 1 line in it.
Just read the content of the file, decode it 100 times and output.
state=$(<base64.txt)
for i in {1..100}; do
state=$(<<<"$state" base64 --decode)
done
echo "$state"
Notes:
Backticks ` are discouraged. Use $(...) instead. bash deprecated and obsolete syntax
for i in cat is a common antipattern in bash. How to read a file line by line in bash
If the file contains one line only, there is no need to iterate over the words in the file.
In bash echo "$item" | is a useless usage of echo (and is also a small risk that it may not work, when ex. item=-e). You can use a here string instead when in bash.
I call the following script from another bash script to check for file changes. If the SHA changes from one execution to the next, the google doc has been updated.
The script (tries to) accept a google drive doc ID as a parameter, then tries a few times to get the info (because gdrive fails randomly). The results are several lines long,so the script does a SHA on the results to get a unique short result.
It was working (when gdrive would return results), so I added the loop and failure message to make it a little more robust, but...
I must be doing something wrong with the if and possibly the while statements in the following script because the script cycles through only once even when the gdrive info results fail. Also when the string to test the length of is set to something deliberately short.
If I had hair, I'd be pulling it out.
#!/bin/bash
maxAttempts=10
minResult=100 # gdrive errors are about 80 characters
# If there was no parameter, give an error
[[ -z $1 ]] && errorMsg="Error: no google docs ID provided as a parameter" && echo $errorMsg && exit 0
# With an ID, get the file info, which includes a timestamp and return the SHA
attemptCount=0
strLength=1
while [[ "$strLength" < "$minResult" && "$attemptCount" < "$maxAttempts" ]];
do
((attemptCount++))
fileInfo="$(gdrive info $1)"
#fileInfo="TESTXXX" # use for testing different message lengths
strLength=${#fileInfo} # if under 100, the grive attempt failed
timeStamp="$(echo -n $fileInfo | sha256sum )"
echo $fileInfo
if [[ $strLength < $minResult ]]; then
sleep 10
timeStamp="Failed to get timestamp after $attemptCount tries, or wrong ID provided"
fi
done
#return the timestamp
echo $timeStamp
With the if statement at the end, I've tried single and double square brackets, double quotes around the variables, -gt and < and even putting in the numerical values 7 and 100 to try and force that section to execute and it is failing. I have if statements in other functioning scripts that look exactly the same. I'm going crazy. What am I not seeing wrong? Help please.
Use round parenthesis for numerical operations:
if (( strLength < minResult )); then
But make sure that the variables contain numerical values. This can be done with declare:
declare -i strLength
declare -i minResult
What i'm trying to do basically is to get the folder size and check if it's greater than X size to do some actions (move files externally)...but the conditionnal doesn't work.
#!/bin/bash
FOLDER_SIZE="5709119"
CHECK=$(du -s /var/backups/ | cut -f1)
echo "Current folder size $CHECK"
echo "Current SIZE LIMIT $FOLDER_SIZE"
if [[ $CHECK -gt $FOLDER_SIZE ]]
then
echo "$CHECK BIGGER THAN $FOLDER_SIZE"
else
echo "$CHECK SMALLER THAN $FOLDER_SIZE"
fi
The problem here is: i'm always getting the size of $check is smaller than $folder_size which not true since the $CHECK folder is mucher bigger than 5GB.
I'm getting as well this error when i run the script:
bk_script.sh: 35:bk_script.sh: [[: not found
Any hints will be much appreciated.
bk_script.sh: 35:bk_script.sh: [[: not found
How are you running your script? The error suggests you're doing something like sh bk_script.sh rather than ./bk_script.sh. Always do the latter so it uses the declared shell /bin/bash rather than /bin/sh. Plain sh does not have a [[ operator.
I am trying to write a bash script that will do the following:
Take a directory or file as input (will always begin with /mnt/user/)
Search other mount points for same file or directory (will always begin with /mnt/diskx)
Return value
So, for example, the input will be "/mnt/user/my_files/file.txt". It will search if ""/mnt/disk1/my_files/file.txt" exists and will incrementally look for each disk (disk2, disk3, etc) until it finds it or disk20.
This is what I have so far:
#/user/bin/bash
var=$1
i=0
while [ -e $check_var = echo $var | sed 's:/mnt/user:/mnt/disk$i+1:']
do
final=$check_var
done
It's incomplete yes, but I am not that proficient in bash so I'm doing a little at a time. I'm sure my command won't work properly yet either but right now I am getting an "unexpected end of file" and I can't figure out why.
There are many issues here:
If this is the actual code you're getting "unexpected end of file" on, you should save the file in Unix format, not DOS format.
The shebang should be #!/usr/bin/bash or #!/bin/bash depending on your system
You have to assign check_var before running [ .. ] on it.
You have to use $(..) to expand a command
Variables like $i are not expanded in single quotes
sed can't add numbers
i is never incremented
the loop logic is inverted, it should loop until it matches and not while it matches.
You'd want to assign final after -- not in -- the loop.
Consider doing it in even smaller pieces, it's easier to debug e.g. the single statement sed 's:/mnt/user:/mnt/disk$i+1:' than your entire while loop.
Here's a more canonical way of doing it:
#!/bin/bash
var="${1#/mnt/user/}"
for file in /mnt/disk{1..20}/"$var"
do
[[ -e "$file" ]] && final="$file" && break
done
if [[ $final ]]
then
echo "It exists at $final"
else
echo "It doesn't exist anywhere"
fi
Currently I'm creating a little script in BASH that will ask the user to fill in a new IP-address, subnet and gateway. That input goes to a file which will be writen to /etc/network/interface..
I got the script working, but it isn't bullet proof.
When the user input, is not a number but an alphabetic character, It returns and the user needs to fill again a number.
When the user still uses a alphabetic character, the script continues, even though giving a error.
My code:
echo "Fill in your IP"
read NEW_IP
oldIFS=$IFS
IFS=.
set -- $NEW_IP
while [ $# -ne "4" ]; do
echo "Must have 4 parts"
read NEW_IP
set -- $NEW_IP
done
for oct in $1 $2 $3 $4; do
echo $oct | egrep "^[0-9]+$" >/dev/null 2>&1
while [ "$?" -ne "0" ]; do
echo "$oct is not numeric. fill your IP in the correct format;"
read NEW_IP
set -- $NEW_IP
done
I'm new with bash, above I didn't make it by my self. I've found this script on the internet. The while and do, I made that by my self as a loop.
Everytime the user fills in a wrong number It must return untill the user filled in a correct format.
The real problem lies at the second half of the code. When I fill in a wrong IP like 10.10.10.a, I get the error like I want and I have to fill in for the second time my IP.
When I type 10.41.12.r, an error occured but this time, not complaining about the r at the end, but still complaining about the a which I inserted at the first. 10.41.12 will be checkt, but that last character is different.
I can imagine that everything will be stored in memory, but how do I clear that?
unset or $oct=
won't work
Hope that someone can help me with this. It's my first time programming, and this is giving me a headache
thanks.
Dave
for does not evaluate the condition several times. It just runs 4 times, setting $oct to $1 .. $4. If you try several times, your input will be accepted, even if not numeric. Moreover, you should check "Must have 4 parts" again after getting the input in the loop.
BTW, you should check that each $oct <= 255.
Duplicated code is often bad. Better read the input at one place and go through the same tests everytime.
prompt="Fill in your IP"
while
echo $prompt
read NEW_IP
IFS=.
set -- $NEW_IP
IFS=
if [ $# -ne 4 ]
then
prompt="Must have 4 parts"
continue
fi
for oct
do if [[ ! "$oct" =~ ^[0-9]+$ ]]
then
prompt="$oct is not numeric. fill your IP in the correct format;"
continue 2
fi
# You might add more checks here.
done
do break
done