-
-
Save nbonamy/85ff67c6c1bb48120917d3935a4794aa 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/bash | |
# Run as if it was called from cron, that is to say: | |
# * with a modified environment | |
# * with a specific shell, which may or may not be bash | |
# * without an attached input terminal | |
# * in a non-interactive shell | |
# This scripts supports cron jobs run by any user, just run it as the target user (e.g. using sudo -u <username>) | |
# An up-to-date version of this script may be available at https://gist.github.com/daladim/7f67eb95d59aadc8f3e8cd66c6f235d3 | |
function usage(){ | |
echo "$0 - Run a script or a command as it would be in a cron job, then display its output" | |
echo "Usage:" | |
echo " $0 [command | script]" | |
echo "" | |
echo "This scripts supports cron jobs run by any user." | |
echo "To do so, just run it as the target user (e.g. using sudo -u <username> $0)" | |
} | |
if [ "$1" == "-h" -o "$1" == "--help" ]; then | |
usage | |
exit 0 | |
fi | |
# Depending on the distro, $HOME may or may not be affected by sudo. | |
# This is a better way to get the home directory of the current user | |
home=$( getent passwd "$(whoami)" | cut -d: -f6 ) | |
cron_env="$home/.config/run-as-cron/cron-env" | |
function generate_env_file(){ | |
# This function adds /usr/bin/env to a cron job and makes sure it is run only once | |
# i.e. it just helps the user who does not want to do it himself | |
echo -n "Adding a job to cron, to be run once... " | |
generator=$(mktemp /tmp/generator.cron.XXXX) | |
chmod 700 "$generator" | |
cat > "$generator" <<eof | |
#!/bin/bash | |
mkdir -p $(dirname "$cron_env") | |
/usr/bin/env > ${cron_env} | |
# Remove this script from the current cron jobs | |
crontab -l | sed "/$(basename $generator)/d" | crontab - | |
rm "$generator" | |
eof | |
# Add the just-created-script to cron | |
crontab -l | { cat; echo "* * * * * $generator"; } | crontab - | |
if [ "$?" -eq 0 ]; then | |
echo "Done at $(date)" | |
echo "It will be run shortly. You can try to run $0 again in a minute." | |
return 0 | |
else | |
echo "Failed." | |
return 2 | |
fi | |
} | |
# This file should contain the cron environment. | |
if [ ! -f "$cron_env" ]; then | |
echo "Unable to find $cron_env" >&2 | |
echo "To generate it, run \"/usr/bin/env > $cron_env\" as a cron job" >&2 | |
echo -n "Do you want this script to do it for you? [y/n] " | |
read reply | |
if [ "$reply" == "y" -o "$reply" == "Y" ]; then | |
generate_env_file | |
exit $? | |
fi | |
exit 1 | |
fi | |
# It will be a nightmare to expand "$@" inside a shell -c argument. | |
# Let's rather generate a string where we manually expand-and-quote the arguments | |
# Note that may fail in case arguments (or environment variables) contain quotes... | |
env_string="/usr/bin/env -i " | |
while read -r line; do | |
env_string="${env_string} \"$line\" " | |
done < "$cron_env" | |
# Do we have a command? | |
if [ "$#" -lt 1 ]; then | |
# Get crontab commands | |
commands=$(crontab -l | grep -v ^# | cut -d ' ' -f 6-) | |
echo "" | |
echo "Select the command you want to run:" | |
echo "$commands" | nl -s'. ' | |
echo "" | |
echo -n "Command number: " | |
read index | |
cmd_string=$(echo "$commands" | sed -n ${index}p 2> /dev/null) | |
if [ "$cmd_string" == "" ]; then | |
echo "Error: Invalid index" | |
exit 1 | |
fi | |
else | |
cmd_string="" | |
for arg in "$@"; do | |
cmd_string="${cmd_string} \"${arg}\" " | |
done | |
fi | |
# Which shell should we use? | |
the_shell=$(grep -E "^SHELL=" "$cron_env" | sed 's/SHELL=//') | |
if [ -z "$the_shell" ]; then | |
echo "Unable to detect what shell should be used for this user." >&2 | |
exit 2 | |
fi | |
echo "Running with $the_shell the following command: $cmd_string" | |
# Let's route the output in a file | |
# and do not provide any input (so that the command is executed without an attached terminal) | |
so=$(mktemp "/tmp/fakecron.out.XXXX") | |
se=$(mktemp "/tmp/fakecron.err.XXXX") | |
"$the_shell" -c "$env_string $cmd_string" >"$so" 2>"$se" < /dev/null | |
echo -e "Done. Here is \033[1mstdout\033[0m:" | |
cat "$so" | |
echo -e "Done. Here is \033[1mstderr\033[0m:" | |
cat "$se" | |
rm "$so" "$se" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment