diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rwxr-xr-x | scripts/vyatta-poweroff.pl | 189 | ||||
-rw-r--r-- | templates/poweroff/at/node.tag/node.def | 7 | ||||
-rw-r--r-- | templates/poweroff/cancel/node.def | 2 | ||||
-rw-r--r-- | templates/poweroff/node.def | 9 | ||||
-rw-r--r-- | templates/poweroff/now/node.def | 5 |
6 files changed, 196 insertions, 17 deletions
diff --git a/Makefile.am b/Makefile.am index d32cc56..410c419 100644 --- a/Makefile.am +++ b/Makefile.am @@ -60,6 +60,7 @@ sbin_SCRIPTS += scripts/vyatta-regen-unpriv-commands.sh bin_sudo_users_SCRIPTS = scripts/vyatta-identify-interface.pl bin_sudo_users_SCRIPTS += scripts/vyatta-delete-log-file.sh bin_sudo_users_SCRIPTS += scripts/vyatta-reboot.pl +bin_sudo_users_SCRIPTS += scripts/vyatta-poweroff.pl bin_sudo_users_SCRIPTS += scripts/vyatta-op-dns-forwarding.pl bin_sudo_users_SCRIPTS += scripts/vyatta-op-dynamic-dns.pl bin_sudo_users_SCRIPTS += scripts/vyatta-clear-conntrack diff --git a/scripts/vyatta-poweroff.pl b/scripts/vyatta-poweroff.pl new file mode 100755 index 0000000..9103900 --- /dev/null +++ b/scripts/vyatta-poweroff.pl @@ -0,0 +1,189 @@ +#!/usr/bin/perl +# +# Module: vyatta-poweroff.pl +# +# **** License **** +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# This code was originally developed by Vyatta, Inc. +# Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc. +# All Rights Reserved. +# +# Based on the original vyatta-reboot script by Stig Thormodsrud +# +# Author: Alex Harpin +# Date: Jan 2015 +# Description: Script to shutdown or schedule a shutdown +# +# **** End License **** +# + +use lib "/opt/vyatta/share/perl5/"; +use Getopt::Long; +use POSIX; +use IO::Prompt; +use Sys::Syslog qw(:standard :macros); + +use strict; +use warnings; + +my $poweroff_job_file = '/var/run/poweroff.job'; + +sub parse_at_output { + my @lines = @_; + + foreach my $line (@lines) { + if ($line =~ /error/) { + return (1, '', ''); + } elsif ($line =~ /job (\d+) (.*)$/) { + return (0, $1, $2); + } + } + return (1, '', ''); +} + +sub is_poweroff_pending { + if ( ! -f $poweroff_job_file) { + return (0, ''); + } + my $job = `cat $poweroff_job_file`; + chomp $job; + my $line = `atq $job`; + if ($line =~ /\d+\s+(.*)\sa root$/) { + return (1, $1); + } else { + return (0, ''); + } +} + +sub do_poweroff { + my $login = shift; + + syslog("warning", "Poweroff now requested by $login"); + if (!system("sudo /sbin/shutdown -h now")) { + exec("sudo /usr/bin/killall sshd"); + } +} + +sub cancel_poweroff { + my ($login, $time) = @_; + + my $job = `cat $poweroff_job_file`; + chomp $job; + system("atrm $job"); + system("rm $poweroff_job_file"); + syslog("warning", "Poweroff scheduled for [$time] - CANCELED by $login"); +} + +my ($action, $at_time, $now); +GetOptions("action=s" => \$action, + "at_time=s" => \$at_time, + "now!" => \$now, +); + +if (! defined $action) { + die "no action specified"; +} + +openlog($0, "", LOG_USER); +my $login = getlogin() || getpwuid($<) || "unknown"; + +if ($action eq "poweroff") { + + my ($rc, $time) = is_poweroff_pending(); + if ($rc) { + if (defined $now) { + cancel_poweroff($login, $time); + do_poweroff($login); + } else { + print "Poweroff already scheduled for [$time]\n"; + exit 1; + } + } + + if (defined $now) { + do_poweroff($login); + } else { + if (prompt("Proceed with poweroff? (Yes/No) [No] ", -ynd=>"n")) { + do_poweroff($login); + } else { + print "Poweroff canceled\n"; + exit 1; + } + } +} + +if ($action eq "poweroff_at") { + if (! -f '/usr/bin/at') { + die "Package [at] not installed"; + } + + if (! defined $at_time) { + die "no at_time specified"; + } + + my ($rc, $rtime) = is_poweroff_pending(); + if ($rc) { + print "Poweroff already scheduled for [$rtime]\n"; + exit 1; + } + + my @lines = `echo true | at $at_time 2>&1`; + my ($err, $job, $time) = parse_at_output(@lines); + if ($err) { + print "Invalid time format [$at_time]\n"; + exit 1; + } + system("atrm $job"); + + print "\nPoweroff scheduled for $time\n\n"; + if (!prompt("Proceed with poweroff schedule? [confirm] ", -y1d=>"y")) { + print "Poweroff canceled\n"; + exit 1; + } + + @lines = `echo "sudo /sbin/shutdown -h now && sudo /usr/bin/killall sshd" | at $at_time 2>&1`; + ($err, $job, $time) = parse_at_output(@lines); + if ($err) { + print "Error: unable to schedule poweroff\n"; + exit 1; + } + system("echo $job > $poweroff_job_file"); + print "\nPoweroff scheduled for $time\n"; + syslog("warning", "Poweroff scheduled for [$time] by $login"); + + exit 0; +} + +if ($action eq "poweroff_cancel") { + + my ($rc, $time) = is_poweroff_pending(); + if (! $rc) { + print "No poweroff currently scheduled\n"; + exit 1; + } + cancel_poweroff($login, $time); + print "Poweroff canceled\n"; + exit 0; +} + +if ($action eq "show_poweroff") { + + my ($rc, $time) = is_poweroff_pending(); + if ($rc) { + print "Poweroff scheduled for [$time]\n"; + exit 0; + } else { + print "No poweroff currently scheduled\n"; + } + exit 1; +} + +exit 1; diff --git a/templates/poweroff/at/node.tag/node.def b/templates/poweroff/at/node.tag/node.def index ccc3b5b..932e04b 100644 --- a/templates/poweroff/at/node.tag/node.def +++ b/templates/poweroff/at/node.tag/node.def @@ -1,6 +1,3 @@ help: Poweroff the system at a future time -allowed: echo -n '<HH:MM>' '<MMDDYY>' '+MM' -run: if /opt/vyatta/bin/vyatta-gettime.pl $3 >/tmp/shutdown.at - then (sudo /sbin/shutdown -h $3 & - disown %?sudo ) >/dev/null 2>&1 - fi +allowed: echo -n '<HH:MM>' '<MMDDYY>' '<midnight>' '<noon>' +run: sudo /opt/vyatta/bin/sudo-users/vyatta-poweroff.pl --action poweroff_at --at_time "$3" diff --git a/templates/poweroff/cancel/node.def b/templates/poweroff/cancel/node.def index c08a72d..c45f17a 100644 --- a/templates/poweroff/cancel/node.def +++ b/templates/poweroff/cancel/node.def @@ -1,2 +1,2 @@ help: Cancel a pending poweroff -run: sudo /sbin/shutdown -c +run: sudo /opt/vyatta/bin/sudo-users/vyatta-poweroff.pl --action poweroff_cancel diff --git a/templates/poweroff/node.def b/templates/poweroff/node.def index 44b8301..ccb7338 100644 --- a/templates/poweroff/node.def +++ b/templates/poweroff/node.def @@ -1,9 +1,2 @@ help: Poweroff the system -run: if [ "$VYATTA_PROCESS_CLIENT" == "gui2_rest" ] - then - sudo /sbin/shutdown -h now && sudo /usr/bin/killall sshd - else - ${vyatta_bindir}/yesno -n "Proceed with poweroff? (Yes/No) [No] " \ - && sudo /sbin/shutdown -h now && sudo /usr/bin/killall sshd - fi - +run: sudo /opt/vyatta/bin/sudo-users/vyatta-poweroff.pl --action poweroff diff --git a/templates/poweroff/now/node.def b/templates/poweroff/now/node.def index d9902cb..6b67572 100644 --- a/templates/poweroff/now/node.def +++ b/templates/poweroff/now/node.def @@ -1,3 +1,2 @@ -help: Poweroff the system now [disruptive] -run: sudo /sbin/shutdown -h now && sudo /usr/bin/killall sshd - +help: Poweroff the system without confirmation +run: sudo /opt/vyatta/bin/sudo-users/vyatta-poweroff.pl --action poweroff --now |