Решения Синан и Нандхпа будут работать для этой задачи.threads
и select
являются мощными инструментами в арсенале программиста Perl, но я бы неохотно предлагал их для чьей-то "первой в мире программы на Perl (sic)".Поэтому я предложу другой подход.
Чтобы упростить формулировку этой проблемы, мы хотим что-то сделать (запустить команду для уничтожения процессов на удаленном сервере), когда что-то еще происходит (заставка активнав течение 15 минут).
use strict;
use warnings;
initialize_program();
until (something_happens()) {
sleep 60;
}
do_something();
exit;
Часть do_something
проста:
sub do_something {
print "*** killing all jla processes on anvil...\n";
$result = `ssh anvil pkill -u jla`;
print "*** should all be dead\n";
print $result;
}
Для части программы something_happens
я бы предложил отправить dbus-monitor
вывод в файл в фоновом режиме и чтение из файла всякий раз, когда вы хотите узнать состояние хранителя экрана.Программа dbus-monitor
производит вывод довольно медленно, и чтение из файлового дескриптора Perl будет иметь тенденцию блокировать (если вы не узнаете и не используете select
).
Я собираюсь настроить команду dbus-monitor
aнемного.Эта команда будет печатать временную метку каждый раз, когда изменяется состояние экранной заставки:
my $command = q[dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver',member='ActiveChanged'" | perl -ne 'print time," $_" if /boolean/'];
, и мы запустим нашу программу, выполнив:
sub initialize_program {
# broken into multiple lines for readability
my $command = q[dbus-monitor --session ]
. q["type='signal',interface='org.gnome.ScreenSaver',member='ActiveChanged'"]
. q[ | perl -ne 'print time," $_" if /boolean/'];
system("$command > /tmp/screensavermonitor &");
}
Теперь, чтобы увидеть,на сколько активна заставка, мы время от времени разбираем /tmp/screensavermonitor
.
sub something_happens {
open (my $fh, '<', '/tmp/screensavermonitor') or return do { warn $!;0 };
my @output = <$fh>;
close $fh;
# we only care about the last output
my $state = pop @output;
if (!defined $state) {
# maybe there's no output yet
return 0;
}
if ($state =~ /false/) {
# screensaver is not active
return 0; # event hasn't happened yet
}
if ($state =~ /true/) {
# screensaver is active -- but for how long?
# start time (in seconds since the epoch) is included in output
my ($screensaver_start_time) = ($state =~ /(\d+)/);
if (time - $screensaver_start_time >= 15 * 60) {
return 1;
} else {
return 0;
}
}
return 0;
}