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.
Related
I made a mount.sh file inspired by balena-storage. It works when I login to the container via the balena.io dashboard where I'm deploying (could be the same elsewhere) and run the script manually. It hangs with unpopulated variables when the container runs the script when starting (a script that runs the script). I think it’s a permissions issue or script running script thing. I'm not sure how to proceed in reading USB device variables.
mount.sh:
# Automatically mount a USB drive by specified volume name.
# Note: make sure to have USB_VOLUME_NAME set in env vars.
# Thanks: https://github.com/balena-io-playground/balena-storage
echo "Checking for USB_VOLUME_NAME..."
echo "A"
if [[ -z $USB_VOLUME_NAME ]]; then
echo "Make sure to set environment variable USB_VOLUME_NAME in order to find a connected USB drive by that label and connect to it. Exiting..." >> /usr/src/app/mount.log
exit 1
fi
echo "B"
# Get device by label env var set in balena.io dashboard device env vars
USB_DEVICE=$(blkid -L $USB_VOLUME_NAME)
if [[ -z $USB_DEVICE ]]; then
echo "Invalid USB_DEVICE name: $USB_DEVICE" >> /usr/src/app/mount.log
exit 1
fi
echo $USB_DEVICE
echo "C"
# Get extra device info
ID_FS_TYPE=${ID_FS_TYPE:=$(/bin/udevadm info -n $USB_DEVICE | /usr/bin/awk -F "=" '/ID_FS_TYPE/{ print $2 }')}
ID_FS_UUID_ENC=${ID_FS_UUID_ENC:=$(/bin/udevadm info -n $USB_DEVICE | /usr/bin/awk -F "=" '/ID_FS_UUID_ENC/{ print $2 }')}
ID_FS_LABEL_ENC=${ID_FS_LABEL_ENC:=$(/bin/udevadm info -n $USB_DEVICE | /usr/bin/awk -F "=" '/ID_FS_LABEL_ENC/{ print $2 }')}
MOUNT_POINT=/mnt/$USB_VOLUME_NAME
echo $ID_FS_TYPE
echo $ID_FS_UUID_ENC
echo $ID_FS_LABEL_ENC
echo $MOUNT_POINT
echo "D"
# Bail if file system is not supported by the kernel
if ! /bin/grep -qw $ID_FS_TYPE /proc/filesystems; then
echo "File system not supported: $ID_FS_TYPE" >> /usr/src/app/mount.log
exit 1
fi
echo "E"
# Mount device
if /bin/findmnt -rno SOURCE,TARGET $USB_DEVICE >/dev/null; then
echo "Device $USB_DEVICE is already mounted!" >> /usr/src/mount.log
else
echo "Mounting - Source: $USB_DEVICE - Destination: $MOUNT_POINT" >> /usr/src/app/mount.log
/bin/mkdir -p $MOUNT_POINT
/bin/mount -t $ID_FS_TYPE -o rw $USB_DEVICE $MOUNT_POINT
fi
echo "F"
When the container runs the script, it gets stuck after "D", with ID_FS_TYPE, ID_FS_UUID_ENC and ID_FS_LABEL_ENC being empty (a good reason to hang).
output:
Checking for USB_VOLUME_NAME...
A
B
/dev/sda1
C
/mnt/MYDRIVE
D
My dockerfile.template:
FROM balenalib/%%BALENA_MACHINE_NAME%%-node
# Enable udev for detection of dynamically plugged devices
ENV UDEV=on
COPY udev/usb.rules /etc/udev/rules.d/usb.rules
# Install dependencies
RUN install_packages util-linux
WORKDIR /usr/src/app
# Move scripts used for mounting USB
COPY scripts scripts
RUN chmod +x scripts/*
# server.js will run when container starts up on the device
CMD ["/bin/bash", "/usr/src/app/scripts/start.sh"]
start.sh:
echo "Mounting USB drive..."
cd /usr/src/app/scripts
/bin/bash mount.sh
# It won't get this far while the script above hangs.
echo "Starting server..."
cd /usr/src/app
/usr/local/bin/yarn run serve
I can confirm that everything works when running from within the container manually:
cd /usr/src/app/scripts
/bin/bash mount.sh
Output:
Checking for USB_VOLUME_NAME...
A
B
/dev/sda1
C
vfat
BE23-31BA
MYDRIVE
/mnt/MYDRIVE
D
E
F
(and the drive mounted)
How would I resolve the empty variables?
Always quote every shell variable you use. (Unless you're absolutely sure of what you're doing, and what you expect to happen if the variable value is empty or includes spaces.)
Without quoting, when you
/bin/grep -qw $ID_FS_TYPE /proc/filesystems
and $ID_FS_TYPE is empty, that word just gets omitted from the command line, so you get
/bin/grep -qw /proc/filesystems
which uses /proc/filesystems as a regexp, and tries to grep over its stdin; this leads to the apparent hang you see.
If instead you quote it:
/bin/grep -qw "$ID_FS_TYPE" /proc/filesystems
it will get an empty string as the regexp parameter and a filename as the input parameter, which will trivially succeed (but not hang).
For similar reasons, I'd expect you'd get a shell syntax error if $USB_VOLUME_NAME is unset, and the whole script will act oddly if that variable name has a space in it.
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.
I am working on a horribly old machine without logrorate.
[ Actually it has busybox 0.6, which is 'void of form' for most purposes. ]
I have openvpn running and I'd like to be able to see what it's been up to. The openvpn I'm using can output progress info to stdout or to a named log file.
I tried and failed to find a way to stop it using one log file and start it on another. Maybe some SIGUSR or something will make it close and re-open the output file, but I can't find it.
So I wrote a script which reads from stdin, and directs output to a rotating log file.
So now all I need to do is pipe the output from openvpn to it.
Job done.
Except that if I kill openvpn, the script which is processing its output just runs forever. There's nothing more it can do, so I'd like it to die automatically.
Is there any way to trap the situation in the script "EOF on STDIN" or something using "find the process ID which is feeding my stdin", or whatever?
I see that this resembles the question
"Tee does not exit after pipeline it's on has finished"
but it's not quite that in that I have no control over the behaviour of openvpn ( save that I can kill it ). I do have control over the script that receives the output of openvpn, but can't work out how to detect the death of openvpn, or the pipe from it to me.
My upper-level script is roughly:
vpn_command="openvpn --writepid ${sole_vpn_pid_file} \
--config /etc/openvpn/openvpn.conf \
--remote ${VPN_HOST} ${VPN_PORT} "
# collapse sequences of multiple spaces to one space
vpn_command_tight=$(echo -e ${vpn_command}) # must not quote the parameter
# We pass the pid file over explicitly in case we ever want to use multiple VPNs.
( ./${launchAndWaitScriptFullName} "${vpn_command_tight}" "${sole_vpn_pid_file}" 2>&1 | \
./vpn-log-rotate.sh 10000 /var/log/openvpn/openvpn.log ) &
if I kill the openvpn process, the "vpn-log-rotate.sh" one stays running.
that is:
#!/bin/sh
# #file vpn-log-rotate.sh
#
# #brief rotates stdin out to 2 levels of log files
#
# #param linesPerFile Number of lines to be placed in each log file.
# #param logFile Name of the primary log file.
#
# Archives the last log files on entry to .last files, then starts clean.
#
# #FIXME DGC 28-Nov-2014
# Note that this script does not die if the previous stage of the pipeline dies.
# It is possible that use of "trap SIGPIPE" or similar might fix that.
#
# #copyright Copyright Dexdyne Ltd 2014. All rights reserved.
#
# #author DGC
linesPerFile="$1"
logFile="$2"
# The location of this script as an absolute path. ( e.g. /home/Scripts )
scriptHomePathAndDirName="$(dirname "$(readlink -f $0)")"
# The name of this script
scriptName="$( basename $0 )"
. ${scriptHomePathAndDirName}/vpn-common.inc.sh
# Includes /sbin/script_start.inc.sh
# Reads config file
# Sets up vpn_temp_directory
# Sets up functions to obtain process id, and check if process is running.
# includes vpn-script-macros
# Remember our PID, to make it easier for a supervisor script to locate and kill us.
echo $$ > ${vpn_log_rotate_pid_file}
onExit()
{
echo "vpn-log-rotate.sh is exiting now"
rm -f ${vpn_log_rotate_pid_file}
}
trap "( onExit )" EXIT
logFileRotate1="${logFile}.1"
# Currently remember the 2 previous logs, in a rather knife-and-fork manner.
logFileMinus1="${logfile}.minus1"
logFileMinus2="${logfile}.minus2"
logFileRotate1Minus1="${logFileRotate1}.minus1"
logFileRotate1Minus2="${logFileRotate1}.minus2"
# The primary log file exist, rename it to be the rotated version.
rotateLogs()
{
if [ -f "${logFile}" ]
then
mv -f "${logFile}" "${logFileRotate1}"
fi
}
# The log files exist, rename them to be the archived copies.
archiveLogs()
{
if [ -f "${logFileMinus1}" ]
then
mv -f "${logFileMinus1}" "${logFileMinus2}"
fi
if [ -f "${logFile}" ]
then
mv -f "${logFile}" "${logFileMinus1}"
fi
if [ -f "${logFileRotate1Minus1}" ]
then
mv -f "${logFileRotate1Minus1}" "${logFileRotate1Minus2}"
fi
if [ -f "${logFileRotate1}" ]
then
mv -f "${logFileRotate1}" "${logFileRotate1Minus1}"
fi
}
archiveLogs
rm -f "${LogFile}"
rm -f "${logFileRotate1}"
while true
do
lines=0
while [ ${lines} -lt ${linesPerFile} ]
do
read line
lines=$(( ${lines} + 1 ))
#echo $lines
echo ${line} >> ${logFile}
done
mv -f "${logFile}" "${logFileRotate1}"
done
exit_0
Change this:
read line
to this:
read line || exit
so that if read-ing fails (because you've reached EOF), you exit.
Better yet, change it to this:
IFS= read -r line || exit
so that you don't discard leading whitespace, and don't treat backslashes as special.
And while you're at it, be sure to change this:
echo ${line} >> ${logFile}
to this:
printf %s "$line" >> "$logFile"
so that you don't run into problems if $line has a leading -, or contains * or ?, or whatnot.
Ive recently been introduced to bash scripting... So, Ive used my advanced theft course to throw together the attached script. it runs... and exits with "/xxx/ not mounted. You are not root! I have rdiff-backup and sshfs installed and working. The commands work fine on their own on the commandline, but in the script, well... Can you guys take a look and lemme know? PS I copied a LOT of this from scripts I found here and a few other places.
<code>
#!/bin/bash
# Version 1.5
# Prior to running this make sure you have ssh-keygen -t rsa to generate a key, then
# ssh username#target "mkdir .ssh/;chmod 700 .ssh"
# scp .ssh/id_rsa.pub username#target:.ssh/authorized_keys
#
# then check you can login and accept the ssh key
# ssh username#target "ls -la"
#
# Key things to remember, no spaces in pathnames, and try to use full paths (beginning with / )
#
# variables determine backup criteria
DATESTAMP=`date +%d%m%y`
USERNAME=username #remote site username here
TARGET=remote.ip.here #add the ip v4 address of the target
INCLUDES=/path/to/file/includes.txt #this is a txt file containing a list of directories you want backed up
EXCLUDES="**" #this is a list of files etc you want to skip
BACKUPLOG=/path/to/logfile/in/home/backuplog${DATESTAMP}.txt
OLDERTHAN=20W #change 20 to reflect how far back you want backups to exist
# to activate old backup expiry, uncomment the line below
#RMARGS=" --force --remove-older-than ${OLDERTHAN}"
TARGETMAIL="yourmailaddress#your.domain"
HOSTNAME=`hostname` #Dont change this!
TMPDIR=/backups Change this to the source folder
TARGETFOLDER=/backups change this to the TARGET folder
ARGS=" -v0 --terminal-verbosity 0 --exclude-special-files --exclude-other-filesystems --no-compression -v6"
# detecting distro and setting the correct path
if [ -e /etc/debian_version ];then
NICE=/usr/bin/nice
elif [ -e /etc/redhat-release ];then
NICE=/bin/nice
fi
if [ -e /tmp/backup.lock ];then
exit 0
fi
touch /tmp/backup.lock
touch -a ${BACKUPLOG}
cd /
/bin/mkdir -p ${TMPDIR}
/usr/bin/sshfs -o idmap=user -o ${USERNAME}#${TARGET}:/${TARGETFOLDER} ${TMPDIR} &>${BACKUPLOG}
# if you get errors mounting this then try
# mknod /dev/fuse -m 0666 c 10 229
for ITEMI in ${INCLUDES} ; do
ARGS="${ARGS} --include ${ITEMI} "
done
for ITEME in ${EXCLUDES} ; do
ARGS="${ARGS} --exclude-regexp '${ITEME}' "
done
# the --exclude ** / is a hack because it wont by default do multiple dirs, so use --include for all dirs then exclude everything else and sync / - if you dont understand dont worry
# ref: http://www.mail-archive.com/rdiff-backup-users#nongnu.org/msg00311.html
#echo /usr/bin/rdiff-backup ${ARGS} --exclude \'**\' / ${TMPDIR}/ &&
cat ${INCLUDES} | while read DIR; do
${NICE} -19 /usr/bin/rdiff-backup --exclude '**' ${DIR} ${TMPDIR}/ &>${BACKUPLOG}
if [ $? != 0 ]; then
echo "System Backup Failed" | mutt -s "Backup Log: System Backup Failed, Log attached!" -a ${BACKUPLOG} ${TARGETMAIL}
exit 1;
fi
done
#${NICE} -19 /usr/bin/rdiff-backup ${ARGS} --exclude '**' / ${TMPDIR}/ &>${BACKUPLOG} &&
echo Removing backups older than ${RMARGS}
${NICE} -19 /usr/bin/rdiff-backup -v0 --terminal-verbosity 0 ${RMARGS} ${TMPDIR}/ &>${BACKUPLOG}
/bin/umount ${TMPDIR} && /bin/rm -rf ${TMPDIR}/ &>${BACKUPLOG}
echo "System Backup Run" | mutt -s "Backup Log: System Backup Done!" -a ${BACKUPLOG} ${TARGETMAIL}
rm /tmp/backup.lock
rm ${BACKUPLOG}
Sorry, cannot paste, couldnt attach... BLIKSEM!
Thanks for ANY input... One HELL of a learning curve!!!
Regards,
B.
Im making a bash script for nagios custom plugins & configuration
i use equivs for its simplicity
here'is my control file.
in Files: section , i tell files to copy themselves to their right path.
Files: check_cpu_loadx /usr/lib/nagios/plugins
check_ipmi_sensors /usr/lib/nagios/plugins
check_libreoffice_count /usr/lib/nagios/plugins
check_ram_per_user /usr/lib/nagios/plugins
check_ram_usage2 /usr/lib/nagios/plugins
check_ram_usage_percentage /usr/lib/nagios/plugins
check_tcptraffic /usr/lib/nagios/plugins
nrpe_custom.cfg /etc/nagios
in the postinst section , it's a bash script that is used for post-install
File: postinst
#!/bin/bash -e
set -x
echo 'configuring nrpe.conf file.'
mv /etc/nagios/nrpe.cfg /etc/nagios/nrpe.original.backup
mv /etc/nagios/nrpe_custom.cfg /etc/nagios/nrpe.cfg
chmod -R +x /usr/lib/nagios/plugins
echo 'Installing tcp-ip addon..'
FLAG=0
Interfaces=`ifconfig -a | grep -o -e "[a-z][a-z]*[0-9]*[ ]*Link" | perl -pe "s|^([a-z]*[0-9]*)[ ]*Link|\1|"`
for Interface in $Interfaces; do
INET=`ifconfig $Interface | grep -o -e "inet addr:[^ ]*" | grep -o -e "[^:]*$"`
MASK=`ifconfig $Interface | grep -o -e "Mask:[^ ]*" | grep -o -e "[^:]*$"`
STATUS="up"
#loopback
if [ "$Interface" == "lo" ]; then
continue
fi
#if eth is down
if [ -z "$INET" ]; then
continue
fi
#if eth ip not starts with 10. or 192.
if [[ "$INET" == 10.* ]]
then
ActiveEth=$Interface;
break
elif [[ "$INET" == 192.* ]]
then
ActiveEth=$Interface;
break
else
echo "Ethernet Selection Failed!Configure nrpe.cfg manually.Change tcp_traffic plugin paramethers according to your current ethernet.";
FLAG=1
break
fi
done
if [[ "$FLAG" == 0 ]]
then
echo 'Selected Ethernet :'$ActiveEth
sed -i -e "s/eth0/$ActiveEth/g" /etc/nagios/nrpe.cfg
fi
echo 'nrpe.conf changed.'
echo 'Nagios-nrpe-server restarting.'
service nagios-nrpe-server restart
echo 'IPMI modules are loading.'
modprobe ipmi_devintf
modprobe ipmi_msghandler
echo "IPMI modules are added to startup."
#echo "ipmi_si" >> /etc/modules
echo "ipmi_devintf" >> /etc/modules
echo "ipmi_msghandler" >> /etc/modules
the problem here , when i compile it to deb package i got "subprocess installed post-installation script return error exit status 1"
then i added set -x for debugging.the problem is for configuring tcp-ip addon , there are some machines that have more then one ethernet card.So i need to choose with the one that has a ip that starts with 10.* or 192.*
in the second section , there is a line
INET=ifconfig $Interface | grep -o -e "inet addr:[^ ]*" | grep -o -e "[^:]*$"
when a ethernet device has no ip , grep returns null and INET variable becomes null , that why the process exit status is 1.
after that line , when i enter "$?" , it says 1
so the problem here is , when i run dpkg -i to install that package , bash script quits after it sees that INET becomes null ..
any help would be appreciated. Im new to this bash thing.
if you want to make sure that a bash command always succeeds, even if the last program gives a non-null return value, just add a "very last" command that will succeed.
something like
INET=$(/sbin/ifconfig eth0 | grep -o -e "inet addr:[^ ]*" | grep -o -e "[^:]*$" || true)
here we call true (a small program that always succeeds), whenever grep fails (|| means OR and is a way to chain programs depending on the exit state of the previous one)
however, your script has a number of flaws:
your grep expression "inet addr:" will only give correct results in an english locale; e.g. when running in a german environment (LANG=de) you could get strings like inet Adresse: 192.168.7.10 (sic!)
you are unconditionally moving files around; what happens if these files are not there?
you are unconditionally moving files in /etc. /etc is the place where the sysadmin adjust the system to their needs; you shall not delete or revert the configuration of the sysadmin. you should rather document how to properly configure the system (so the sysadmins can do it themselves); if you insist in "helping" by automatically configuring the system, you should use something like debconf
you assume that a lot of software is installed, and that this software is in your path. you should probably use fully qualified paths to the binaries you are using, e.g. /sbin/ifconfig rather than just ifconfig