Bash shell script not working - bash

I have a script I am trying to work out to scan my LAN and send me notification if there is a new MAC address that does not appear in my master list. I believe my variables may be messed up. This is what I have:
#!/bin/bash
LIST=$HOME/maclist.log
MASTERFILE=$HOME/master
FILEDIFF="$(diff $LIST $MASTERFILE)"
# backup the maclist first
if [ -f $LIST ]; then
cp $LIST maclist_`date +%Y%m%H%M`.log.bk
else
touch $LIST
fi
# this will scan the network and extract the IP and MAC address
nmap -n -sP 192.168.122.0/24 | awk '/^Nmap scan/{IP=$5};/^MAC/{print IP,$3};{next}' > $LIST
# this will use a diff command to compare the maclist created above and master list of known good devices on the LAN
if [ $FILEDIFF ] 2> /dev/null; then
echo
echo "---- All is well on `date` ----" >> macscan.log
echo
else
# echo -e "\nWARNING!!" | `mutt -e 'my_hdr From:user#email.com' -s "WARNIG!! NEW DEVICE ON THE LAN" -i maclist.log user#email.com`
echo "emailing you"
fi
When I execute this when the maclist.log does not exist I get this response:
diff: /root/maclist.log: No such file or directory
If I execute it again with the maclist.log file existing the file gets renamed from the cp line without any issue.

The line
FILEDIFF="$(diff $LIST $MASTERFILE)"
executes the diff when it is run (not when you use $FILELIST later). At that time the list file hasn't been created.
The easiest fix is just to put the diff command in full where $FILELIST is currently used.

Related

Problem with if loop when trying send a few files

I need sending a few files to FTP server but the following script runs only one time, even if there are more entries in the document that have string "example". In /abc.txt I have paths to files which I want sending to FTP server.
#!/bin/sh
if grep -q example "/abc.txt" ;
then
var=$( cat /abc.txt )
HOST='X.X.X.X'
USER='USER'
PASSWD='PASSWORD'
cd $var
FILE='./*.txt'
ftp -nv $HOST > /abc.log.txt <<ENDSCRIPT
quote USER $USER
quote PASS $PASSWD
passive
put $FILE
bye
quit
ENDSCRIPT
echo $FILE
sed -i '1d' "/abc.txt"
else
echo "error"
fi
I recommend using for, and I think using -q option for grep here is unnecessary:
for var in $(grep example ./abc.txt); do
your_code_here
done
Here var will each time contain the name of the file.

Download a fix number of directories from ftp server

I have an FTP server with thousands of directories. What I want to do is to download a specific number of them (for example, 500 directories) using a shell script. How can I do that? I tried wget with -Q command. For example, "wget -Q25MB", which gives me 25MB of data. The problem is that each folder has a different size. Therefore, using this command will stop the download in the middle of getting a specific folder.
Assuming wget returns an error when the download get interrupted:
#!/bin/bash
to_del= # empty to_del in case you want to copy-paste this to a terminal instead of using a file
username=blablabla
password=blablabla
server=blablabla
printf -v today '%(%Y_%m_%d)T'
# Get the 500 first directory names to download
ftp -n "$server" << EOF | grep -v '^\.\.\?$' | head -n 502 > "to_download_$today.txt"
user $username $password
ls
bye
EOF
# Then, you can download each folder one by one:
while read -r dir; do
if [[ -e $dir ]]; then
echo >&2 "WARNING: '$dir' already exists!"
continue # We don't download or remove it. Manual action needed
fi
if wget "$username:$password#$server/$dir"; then
to_del+=("$dir")
else
# A directory was not successfully downloaded, we delete the temporary files
echo >&2 "WARNING: '$dir' download failed, skipping..."
rm -rf "$dir"
fi
done < "to_download_$today.txt"
# Now, delete the successfully downloaded folders using a single FTP connection
{
printf 'user %s %s\n' "$username" "$password"
for dir in "${to_del[#]}"; do
printf 'del %s\n' "$dir"
done
printf 'bye\n'
} | ftp -i -n "$server"

Bash: Check if remote directory exists using FTP

I'm writing a bash script to send files from a linux server to a remote Windows FTP server.
I would like to check using FTP if the folder where the file will be stored exists before attempting to create it.
Please note that I cannot use SSH nor SCP and I cannot install new scripts on the linux server. Also, for performance issues, I would prefer if checking and creating the folders is done using only one FTP connection.
Here's the function to send the file:
sendFile() {
ftp -n $FTP_HOST <<! >> ${LOCAL_LOG}
quote USER ${FTP_USER}
quote PASS ${FTP_PASS}
binary
$(ftp_mkdir_loop "$FTP_PATH")
put ${FILE_PATH} ${FTP_PATH}/${FILENAME}
bye
!
}
And here's what ftp_mkdir_loop looks like:
ftp_mkdir_loop() {
local r
local a
r="$#"
while [[ "$r" != "$a" ]]; do
a=${r%%/*}
echo "mkdir $a"
echo "cd $a"
r=${r#*/}
done
}
The ftp_mkdir_loop function helps in creating all the folders in $FTP_PATH (Since I cannot do mkdir -p $FTP_PATH through FTP).
Overall my script works but is not "clean"; this is what I'm getting in my log file after the execution of the script (yes, $FTP_PATH is composed of 5 existing directories):
(directory-name) Cannot create a file when that file already exists.
Cannot create a file when that file already exists.
Cannot create a file when that file already exists.
Cannot create a file when that file already exists.
Cannot create a file when that file already exists.
To solve this, do as follows:
To ensure that you only use one FTP connection, you create the input (FTP commands) as an output of a shell script
E.g.
$ cat a.sh
cd /home/test1
mkdir /home/test1/test2
$ ./a.sh | ftp $Your_login_and_server > /your/log 2>&1
To allow the FTP to test if a directory exists, you use the fact that "DIR" command has an option to write to file
# ...continuing a.sh
# In a loop, $CURRENT_DIR is the next subdirectory to check-or-create
echo "DIR $CURRENT_DIR $local_output_file"
sleep 5 # to leave time for the file to be created
if (! -s $local_output_file)
then
echo "mkdir $CURRENT_DIR"
endif
Please note that "-s" test is not necessarily correct - I don't have acccess to ftp now and don't know what the exact output of running DIR on non-existing directory will be - cold be empty file, could be a specific error. If error, you can grep the error text in $local_output_file
Now, wrap the step #2 into a loop over your individual subdirectories in a.sh
#!/bin/bash
FTP_HOST=prep.ai.mit.edu
FTP_USER=anonymous
FTP_PASS=foobar#example.com
DIRECTORY=/foo # /foo does not exist, /pub exists
LOCAL_LOG=/tmp/foo.log
ERROR="Failed to change directory"
ftp -n $FTP_HOST << EOF | tee -a ${LOCAL_LOG} | grep -q "${ERROR}"
quote USER ${FTP_USER}
quote pass ${FTP_PASS}
cd ${DIRECTORY}
EOF
if [[ "${PIPESTATUS[2]}" -eq 1 ]]; then
echo ${DIRECTORY} exists
else
echo ${DIRECTORY} does not exist
fi
Output:
/foo does not exist
If you want to suppress only the messages in ${LOCAL_LOG}:
ftp -n $FTP_HOST <<! | grep -v "Cannot create a file" >> ${LOCAL_LOG}

How to change parameter in a file, only if the file exists and the parameter is not already set?

#!/bin/bash
# See if registry is set to expire updates
filename=hostnames
> test.log
PARAMETER=Updates
FILE=/etc/.properties
CODE=sudo if [ ! -f $FILE] && grep $PARAMETER $FILE; then echo "File found, parameter not found."
#CODE=grep $PARAMETER $FILE || sudo tee -a /etc/.properties <<< $PARAMETER
while read -r -a line
do
hostname=${line//\"}
echo $hostname":" >> test.log
#ssh -n -t -t $hostname "$CODE" >> test.log
echo $CODE;
done < "$filename"
exit
I want to set "Updates 30" in /etc/.properties on about 50 servers if:
The file exists (not all servers have the software installed)
The parameter "Updates" is not already set in the file (e.g. in case of multiple runs)
I am a little puzzled so far how, because I am not sure if this can be done in 1 line of bash code. The rest of the script works fine.
Ok, here's what i think would be a solution for you. Like explained in this article http://www.unix.com/shell-programming-scripting/181221-bash-script-execute-command-remote-servers-using-ssh.html
invoke the script which contains the commands that you want to be executed at the remote server
Code script 1:
while read -r -a line
do
ssh ${line} "bash -s" < script2
done < "$filename"
To replace a line in a text file, you can use sed (http://www.cyberciti.biz/faq/unix-linux-replace-string-words-in-many-files/)
Code script 2:
PARAMETER=Updates
FILE=/etc/.properties
NEWPARAMETER=Updates ###(What you want to write there)
if [ ! -f $FILE] && grep $PARAMETER $FILE; then exit
sed -i 's/$PARAMETER/$NEWPARAMETER/g' $FILE
So, I'm not certain this covers all your use case, I hope this helps you out if there is anything feel free to ask!

Clonezilla custom-ocs bash script failing on ocs-onthefly command

I'm doing a custom clonezilla.. one for source to send a local disk to remote disk with ocs-onthefly... that custom-ocs is working fine.
However, the custom-ocs for the destination for some reason is not working.. the problem is the last line "/usr/sbin/ocs-onthefly -s $src_ip -t $dest_disk" .. for some reason clonezilla is balking at that line and gives the usage/help output instead of running the command..
Any ideas on why the ocs-onthefly command is not accepting the parameters? The parameters are correct. If you run "/usr/sbin/ocs-onthefly -s 192.168.150.1 -t sda" it runs fine.
custom-ocs for destination script is here: https://www.dropbox.com/s/9mfrt0n50sheayn/custom-ocs_destination-REVISED.txt
Attempting a code block also:
#!/bin/bash
# Author: Steven Shiau <steven _at_ nchc org tw>
# License: GPL
# Ref: http://sourceforge.net/forum/forum.php?thread_id=1759263&forum_id=394751
# In this example, it will allow your user to use clonezilla live to choose
# (1) backup the image of /dev/hda1 (or /dev/sda1) to /dev/hda5 (or /dev/sda5)
# (2) restore image in /dev/hda5 (or /dev/sda5) to /dev/hda1 (or /dev/sda1)
# When this script is ready, you can run
# ocs-iso -g en_US.UTF-8 -k NONE -s -m ./custom-ocs
# to create the iso file for CD/DVD. or
# ocs-live-dev -g en_US.UTF-8 -k NONE -s -c -m ./custom-ocs
# to create the zip file for USB flash drive.
# Begin of the scripts:
# Load DRBL setting and functions
DRBL_SCRIPT_PATH="${DRBL_SCRIPT_PATH:-/usr/share/drbl}"
. $DRBL_SCRIPT_PATH/sbin/drbl-conf-functions
. /etc/drbl/drbl-ocs.conf
. $DRBL_SCRIPT_PATH/sbin/ocs-functions
# load the setting for clonezilla live.
[ -e /etc/ocs/ocs-live.conf ] && . /etc/ocs/ocs-live.conf
# Load language files. For English, use "en_US.UTF-8".
ask_and_load_lang_set en_US.UTF-8
# The above is almost necessary, it is recommended to include them in your own custom- ocs.
# From here, you can write your own scripts.
# functions
decide_sda_or_hda() {
if [ -n "$(grep -Ew sda1 /proc/partitions)" ]; then
disk=sda
elif [ -n "$(grep -Ew hda1 /proc/partitions)" ]; then
disk=hda
else
[ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
echo "No hard disk detected!"
echo "Program terminated!"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
fi
# src_part: hda1 or sda1, tgt_part: hda5 or sda5
dest_disk=${disk}
}
##################
###### MAIN ######
##################
# Set network on destination workstation 1
# Determine if active link then set act_eth
while [ -z "$(/sbin/mii-tool 2>/dev/null | awk -F ":" '/link ok/ {print $1}')" ]; do
dialog --title "NO LINK!!" --msgbox "\n Need an active link in order to continue!!" 6 50
done
act_eth=`/sbin/mii-tool 2>/dev/null | awk -F ":" '/link ok/ {print $1}'`
# Set IP Address of destination workstation 1
/sbin/ifconfig $act_eth 192.168.150.2 netmask 255.255.255.0 up
/sbin/route add default gw 192.168.150.254
/bin/echo "nameserver 8.8.8.8" >> /etc/resolv.conf
# Find the disk device
decide_sda_or_hda
# Prompt for IP address of source disk
OUTPUT="./input.txt"
>$OUTPUT
dialog --title "Need SOURCE IP" --inputbox "Enter IP address of the SOURCE server: " 8 60 2>$OUTPUT
src_ip=$(<$OUTPUT)
# Ready the destination disk to receive from source (source should already be waiting in clonezilla), and contact source to start transfer to destination
/usr/sbin/ocs-onthefly -s $src_ip -t $dest_disk
When I test via echo (not within clonezilla but just on a linux box) the dialog output for $src_ip and also $dest_disk it outputs the variables fine, so I really don't know why ocs-onthefly is not accepting it.
Looks like your ocs-onthefly command is getting unexpected arguments. To analyze, lets see the actual command with
echo /usr/sbin/ocs-onthefly -s $src_ip -t $dest_disk
Or, maybe even better, the result of running your script with
bash -x script
will tell you what is wrong.

Resources