#perl #perl-module
#perl #perl-модуль
Вопрос:
Мне нужно написать сценарий perl, который выполняет команду в указанное время.
- используйте net::ssh::ожидайте входа в маршрутизатор
- считывает время с часов маршрутизатора (команда «показать часы» отображает время.)
- В 17:30:00 выполнить команду.
Я пытался написать для нее скрипт, но он не работает. Какие-либо предложения, пожалуйста?
use strict;
use warnings;
use autodie;
use feature qw/say/;
use Net::SSH::Expect;
my $Time;
my $ssh = Net::SSH::Expect->new(
host => "ip",
password => 'pwd',
user => 'user name',
raw_pty => 1,
);
my $login_output = $ssh->login();
while(1) {
$Time = localtime();
if( $Time == 17:30:00 ) {
my $cmd = $ssh->exec("cmd");
print($cmd);
} else {
print" Failed to execute the cmd n";
}
}
Комментарии:
1. Я совершенно уверен, что это не работает, оно даже не компилируется. Я думаю, вам нужно попробовать немного больше…
2. Из любопытства, почему не cron для * nix или планировщика задач для Windows?
3. @ Chris Hamel: этот perl-скрипт будет интегрирован с другим perl-скриптом. Поэтому я не хочу устанавливать CRON.
Ответ №1:
Здесь несколько вещей:
Во-первых, используйте Time::Piece
. Теперь это включено в Perl.
use Time::Piece;
for (;;) { # I prefer using "for" for infinite loops
my $time = localtime; # localtime creates a Time::Piece object
# I could also simply look at $time
if ( $time->hms eq "17:30:00" ) {
my $cmd $ssh->exec("cmd");
print "$cmdn";
}
else {
print "Didn't execute commandn";
}
}
Во-вторых, вы не должны использовать подобный цикл, потому что вы собираетесь связывать процесс, просто повторяя цикл снова и снова. Вы можете попробовать перейти в режим ожидания до нужного времени:
use strict;
use warnings;
use feature qw(say);
use Time::Piece;
my $time_zone = "-0500"; # Or whatever your offset from GMT
my $current_time = local time;
my $run_time = Time::Piece(
$current_time->mdy . " 17:30:00 $time_zone", # Time you want to run including M/D/Y
"%m-%d-%Y %H:%M:%S %z"); # Format of timestamp
sleep $run_time - $current_time;
$ssh->("cmd");
...
Что я здесь сделал, так это вычислил разницу между временем, которое вы хотите выполнить свою команду, и временем, которое вы хотите выполнить команду. Проблема возникает только в том случае, если я запускаю этот скрипт после 5:30 вечера по местному времени. В этом случае мне, возможно, придется проверить на следующий день.
Или, что еще лучше, если вы работаете в Unix, найдите crontab и используйте его. Crontab позволит вам точно указать, когда должна выполняться конкретная команда, и вам не нужно беспокоиться о ее вычислении в вашей программе. Просто создайте запись в таблице crontab:
30 17 * * * my_script.pl
30
И 17
скажите, что вы хотите запускать свой скрипт каждый день в 5:30 вечера. Другие звездочки обозначают день месяца, месяц и день недели. Например, вы хотите запускать свою программу только в будние дни:
30 17 * * 1-5 my_script.pl # Sunday is 0, Mon is 1...
В Windows есть аналогичный метод, называемый панелью управления расписанием, где вы можете настроить задания, которые выполняются в определенное время. Возможно, вам придется использовать perl my_scipt.pl
, поэтому Windows знает, как использовать интерпретатор Perl для выполнения вашей программы.
Я настоятельно рекомендую использовать маршрут crontab. Это эффективно, гарантированно работает, позволяет вам сосредоточиться на вашей программе и не обманывать, когда выполнять вашу программу. Кроме того, он гибкий, все об этом знают, и никто не убьет вашу задачу, пока она сидит там и ждет 5:30 вечера.
Ответ №2:
localtime
преобразует временную метку Unix (секунды с момента epoch, которая сейчас составляет около 1,4 миллиарда) в список значений. time
Функция удобно предоставляет эту временную метку. От perldoc -f localtime
:
Converts a time as returned by the time function to a 9-element
list with the time analyzed for the local time zone. Typically
used as follows:
# 0 1 2 3 4 5 6 7 8
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
Для вашего сравнения времени вы могли бы сделать:
$Time = join ':', (localtime(time))[2, 1, 0];
if ($Time eq '17:30:00') {
...
}
Поскольку Perl позволяет [...]
оператору postcircumfix индексировать списки точно так же, как это делается с массивами, мы можем использовать его для удаления фрагмента (localtime(time)) список, содержащий часы, минуты и секунды, соедините их двоеточиями и присвоите результирующей строке значение $Time.
Обратите внимание, что, поскольку $Time теперь содержит строку, вы должны сравнить ее с '17:30:00'
, а не с простым словом 17:30:00
, которое не является допустимой числовой формой и должно привести к ошибке компиляции. И поскольку мы сравниваем строки вместо чисел, мы используем eq
оператор. ==
вызывает числовой контекст для своих операндов, и поскольку 17:30:00 не является допустимым числом, Perl обработает его как 0 и предупредит вас с помощью
Argument "foo" isn't numeric in numeric eq (==) at ....