Last active
May 28, 2019 08:11
-
-
Save zatricky/3b4f00f7ec95f2439275177b7ee06ff4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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