Skip to content

Instantly share code, notes, and snippets.

@zatricky
Last active May 28, 2019 08:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zatricky/3b4f00f7ec95f2439275177b7ee06ff4 to your computer and use it in GitHub Desktop.
Save zatricky/3b4f00f7ec95f2439275177b7ee06ff4 to your computer and use it in GitHub Desktop.
#!/bin/sh
#
# NAME: mkscript
# Description: Creates a basic script using itself as a template
# Created: 2013-09-12
# Updated: 2018-06-02
# Version: 0.14.2
# Copyright (C) Brendan Hide 2013-2018
# License: MIT License (Expat)
# See https://opensource.org/licenses/MIT and https://en.wikipedia.org/wiki/MIT_License
# Remember to update the Copyright and Author(s) lines to include principal authors/owners/etc
# TODO: Set dates automatically
# Allow template variable choices (compatible licenses perhaps?, copyright, mutex, etc)
# Allow Mutex to wait instead of quit
# Automatically detect interactive shell and Ignore Delay appropriately
#
#====================# WARNING #=====================#
# DO NOT EDIT THIS FILE DIRECTLY IF IT IS STORED #
# USING A CENTRAL REPOSITORY. YOUR CHANGES WILL BE #
# OVERWRITTEN! INSTEAD, MAKE CHANGES AT THE PATH #
# SPECIFIED BELOW. #
#====================# WARNING #=====================#
#
# Central Repository Path:
# https://gist.github.com/zatricky/
#
# Author(s): Brendan Hide / zatricky
set -u #nounset - quit on any use of a variable that has not been initialised
set -e #noerror - quit on any error
#set -x #debug mode
## Initialize variables
SELF=${0##*/}
FULLSELF=$(dirname ${0})/$SELF
SHA2SELF=$(echo ${FULLSELF} | openssl sha256 | awk '{print $2}')
LOCKFILE=/tmp/${SELF}.${SHA2SELF}.lock
MUTEX="false"
DELAYMAX=0 #Set a random delay in seconds before executing main()
#TMP is updated later with the mutex checks. We define it here in advance as we'd like to use it within main()
TMP=""
main(){
if [ ${#} -lt 1 ] ; then
echo "Error. Please specify the destination file."
exit 1
fi
newscript=${1}
if [ -f ${newscript} ] ; then
echo "Error. Refusing to overwrite ${newscript}."
exit 1
else
if ( set -o noclobber; cat ${FULLSELF} > ${newscript} ) ; then
chmod +x ${newscript}
else
echo "Error writing to ${newscript}."
fi
fi
}
cleanup(){
#This step is for the (however unlikely) case that a filesystem might be
#mounted within our temporary folder. If we don't do this, the step
#thereafter will delete all content in the mounted filesystem.
while true ; do
mount | grep ${TMP} || break
for i in $(mount | grep ${TMP} | awk '{print $3}') ; do
umount ${i}
done
done
#Remove TMP
rm ${TMP} -rf
}
#Leave this here for Debug
echo "STARTING ${0}" > /dev/null
echo $(date "+%Y-%m-%d-%Hh%Mm%Ss%z") > /dev/null
#Pseudo-random delay applicable to cluster/parallel operations
if ! [ ${DELAYMAX} -eq 0 ] ; then
wait_time=$$
wait_time=$((wait_time % DELAYMAX))
sleep ${wait_time}
fi
#Capture current date
STARTDATE=$(date "+%Y-%m-%d - %Hh%M")
NUMDATE=$(date "+%s")
ISO_DATE_SECONDS=$(date -Is)
#Prevent $SELF from running simultaneously
if [ "${MUTEX}" = true ] ; then
if [ -f "${LOCKFILE}" ] ; then
other_pid=$(cat "${LOCKFILE}")
if [ "$?" != 0 ]; then
# existing pid file does not exist - probably being deleted by existing process that is finishing up
echo "SKIPPED running ${SELF} due to existing process busy with cleanup" > /dev/null
exit 0
fi
if grep ${SELF} /proc/${other_pid}/cmdline > /dev/null ; then
# appears to be running already. checkall skipped
echo "SKIPPED running ${SELF} due to existing process" > /dev/null
exit 0
else
#We reach this point only if the file exists but that instance is actually dead/not running. We can safely remove the lock file
rm -f ${LOCKFILE}
fi
fi
#We use an atomic mutex check in case multiple instances did the above check simultaneously
if ( set -o noclobber; echo $$ > "${LOCKFILE}") 2> /dev/null ; then
#We don't use rm -rf as it has the danger of deleting our entire filesystem in the rare case that the unmount fails
trap 'rm -f "${LOCKFILE}"; cleanup ; exit $?' INT TERM EXIT
TMP=$(mktemp -d)
#Run!
main $*
#Close off the trap
rm -f ${LOCKFILE}
#Remove TMP
cleanup
trap - INT TERM EXIT
#Leave this here for Debug
echo "FINISHED running ${0}" > /dev/null
echo $(date "+%Y-%m-%d-%Hh%Mm%Ss%z") > /dev/null
else
#Leave this echo here for Debug
echo "SKIPPED running ${SELF} due to existing process" > /dev/null
echo $(date "+%Y-%m-%d-%Hh%Mm%Ss%z") > /dev/null
fi
else # Skip Mutex checks
#Create TMP
TMP=$(mktemp -d)
main ${*}
#Remove TMP
cleanup
#Leave this here for Debug
echo "FINISHED running ${0}" > /dev/null
echo $(date "+%Y-%m-%d-%Hh%Mm%Ss%z") > /dev/null
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment