Премини към съдържанието
Форумът в приложение

По-лесно сърфиране. Научи повече.

Kaldata.com - Форуми

Приложение на форума на цял екран с push известия, значки и други.

За да инсталирате това приложение на iOS и iPadOS
  1. Докоснете Иконата за споделяне в Safari
  2. Превъртете менюто и докоснете Добавяне към началния екран.
  3. Докоснете Добавяне в горния десен ъгъл.
За да инсталирате това приложение на Android
  1. Докоснете менюто с 3 точки (⋮) в горния десен ъгъл на браузъра.
  2. Докоснете Добавяне към началния екран или Инсталиране на приложение.
  3. Потвърдете, като докоснете Инсталиране.

Добре дошли!

Добре дошли в нашите форуми, пълни с полезна информация. Имате проблем с компютъра или телефона си? Публикувайте нова тема и ще намерите решение на всичките си проблеми. Общувайте свободно и открийте безброй нови приятели.

Моля, регистрирайте се за да публикувате тема и да получите пълен достъп до всички функции.

 

Помощ за Perl

Featured Replies

Здравейте, нужна ми е малко помощ за един скрипт. Налага ми се да направя известна промяна, но тъй като никога не съм работил с Perl ми идва доста нанагорно. Не познавам толкова добре синтаксиса, а и ...алгоритъма нещо ми убягва. sad.gif

________________________________________

#!/usr/bin/perl

$critical = 27;

$lock = "temp.lock";

$string = `tail -1 tempdaemon.temp`;

($date,$time,$temp) = split(" ",$string);

if ($temp >= "$critical" && !(-f $lock)) {

print "Allert";

system("/usr/bin/touch $lock");

}

if ($temp < "$critical" && -f $_lock) {

`/bin/rm $lock`;

________________________________________

Както се вижда, скрипта дърпа переодично данни от един файл - tempdaemon.temp

в който се записва температурата всяка минута.

Скрипта е за уведомяване ако температурата се покачи над 27 градуса. Проблема е, че ако се качи над въпросните 27 градуса на всяка 1 минута изпраща съобщение, което е прекалено в случей, че температурата се задържи примерно на 27.1 в продължение на часове.

Идеята е така да се модифицира скрипта, че да праща съобщение само ако е над 27 градуса И разликата с предходното изпращане е повече от 0.5 градуса.

Благодаря много предварително. Всякакви идеи са добре дошли.

П.П. Хрумна ми, че евентуално може да има един файл в който да се записва стойността на една вариабла, която започва от "critical" и се променя само ако разликата между нея и "temp" е поне 0.5(в двете посоки), и съответно да има съобщение само при промяна на вариаблата. Така, че в момента въпроса е по скоро кода с който мога да трия/записвам във файл!

Редактирано от Axel (преглед на промените)

От това, което си обяснил подразбирам, че въпросният скрипт се изпълнява на всяка минута?

Като гледам кода, който си дал (текущия) - всъщност идеята е след като се алармира веднъж да не се алармира повторно, докато не падне температурата под критичната. Това се осигурява от $lock файла, който се създава при първото превишаване на критичната температура, и се изтрива при падане на температурата под критичната. Ако $lock файлът съществува - не се изпраща съобщение, каквато и да е температурата.

Това е идеята на текущия код, а може би не работи така, както се очаква, поради липса на права за създаване на $lock файла. Провери дали имаш права за писане в директорията, от която се стартира скрипта или премести $lock файла другаде. Също виждам в последния if една подчертавка повече; т.е. би трябвало да изглежда така:

if ($temp < "$critical" && -f $lock) {

`/bin/rm $lock`;

}

Иначе конкретно за чете/писане от файл пробвай така:

#!/usr/bin/perl

my $file="test.txt";


open ( INFILE, "<$file" ) or die "Can't open $file: $!\n";

@lines = <INFILE>;

print "First line is: $lines[0]\n";

close INFILE;

open ( OUTFILE, ">$file" ) or die "Can't open $file: $!\n";

print OUTFILE "Experiment";

close OUTFILE;

  • Автор
От това, което си обяснил подразбирам, че въпросният скрипт се изпълнява на всяка минута?

Като гледам кода, който си дал (текущия) - всъщност идеята е след като се алармира веднъж да не се алармира повторно, докато не падне температурата под критичната. Това се осигурява от $lock файла, който се създава при първото превишаване на критичната температура, и се изтрива при падане на температурата под критичната. Ако $lock файлът съществува - не се изпраща съобщение, каквато и да е температурата.

Това е идеята на текущия код, а може би не работи така, както се очаква, поради липса на права за създаване на $lock файла. Провери дали имаш права за писане в директорията, от която се стартира скрипта или премести $lock файла другаде. Също виждам в последния if една подчертавка повече; т.е. би трябвало да изглежда така:

Иначе конкретно за чете/писане от файл пробвай така:

#!/usr/bin/perl

my $file="test.txt";


open ( INFILE, "<$file" ) or die "Can't open $file: $!\n";

@lines = <INFILE>;

print "First line is: $lines[0]\n";

close INFILE;

open ( OUTFILE, ">$file" ) or die "Can't open $file: $!\n";

print OUTFILE "Experiment";

close OUTFILE;

divak, първо едно ГОЛЯМО, ГОЛЯМО БЛАГОДАРЯ!!!

Явно няма много други хора, които да се занимават със по-сериозно кодиране на Perl;)

Вероятно аз не съм обяснил много добре - целта която искам да постигна е следната - да започнат да се изпращат съобщения само когато температурата е над 27 градуса, и то на половин градус разлика, а не всяка една минута(както е в момента), когато системата проверява температурата, и записва резултата в "tempdaemon.temp.

В момента всяка минута (когато е над 27 градуса) получавам съобщение, което е много досадно(и скъпо защото са СМС), защото се случва температурата да се задържи между 27.1 и 27.3 в продължение на часове,защото на практика за два часа изменението е половин градус, но получаваме 120 съобщения. Затова искам да се получават съобщения само при промяна на температурата(в която и да е посока) с половин градус. Т.е. да има съобщения само когато се прекрачват границите на 0.5 гр в която и да е посока(27.0-27.5-28.0-28.5-29.0-29.5-30.0.... ). Ще дам и пример за още по-голяма яснота:

18:00 - 27.0 гр - съобщение

18:01 - 27.1 гр - нищо

.....

18:04 - 27.4 гр - нищо

18:05 - 27.5 гр - съобщение

18:06 - 27.7 гр - нищо

......

18:25 - 27.5 гр - съобщение

18:27 - 27.1 гр - нищо

....

Още веднъж - много благодаря!!! А ако можеш да ми предложиш решение - отново ще ти вдигна репутацията, и то напълно заслужено!

Редактирано от Axel (преглед на промените)

Честно казано и аз не се занимавам "сериозно" с кодиране на Perl, ама колкото да свършим работата май ще се оправя cool.gif Мисля, че следното в общи линии прави това, което си казал, че искаш:

#!/usr/bin/perl

#

# Critical temperature alerter

########################################################


use POSIX qw( ceil floor );


# some constants

#

my $critical = 27;

##my $lock = "/tmp/temp.lock";

my $tempdaemon_file = '/tmp/tempdaemon.temp';

my $checked_file = "/tmp/tempdaemon_checked.temp";

my $record_delim = "\n";

my $field_delim = " ";


########################################################

# get max 0.5-tick less or equal to x

#

sub get_midpoint

{

		my $x = shift;

		my $fx = floor( $x );

		my $diff = $x - $fx;


		if ( $diff >= 0.5 )

		{

				return $fx + 0.5;

		}

		else

		{

				return $fx;

		}

}

########################################################


########################################################

# Get the last line from the given file 

#

sub get_file_last_line

{

	my $file_name = shift;

	my $fll_cmd = "tail -1 $file_name";

	my $last_line = `$fll_cmd`;


	return $last_line;

}

########################################################


my $last_line_tempdaemon = get_file_last_line( $tempdaemon_file );

my $last_line_checked = get_file_last_line( $checked_file );


chomp( $last_line_tempdaemon );

chomp( $last_line_checked );


if ( $last_line_tempdaemon ne "" )

{

	( $date2, $time2, $temp2 ) = split( $field_delim, $last_line_tempdaemon );


	if ( $last_line_checked ne "" )

	{ 

		( $date1, $time1, $temp1 ) = split( $field_delim, $last_line_checked );

	}

	else

	{

		# simulate "no-change" if the "checked" file was empty

		( $date1, $time1, $temp1 ) = ( $date2, $time2, $temp2 ); 

	}


	if ( $temp2 >= $temp1 )

	{

		$high_value = $temp2;

		$low_value = $temp1;

	}

	else

	{

		$high_value = $temp1;

		$low_value = $temp2;

	}


	if ( $temp2 >= $critical )

	{

		my $mid_value = get_midpoint( $high_value );

		if ( ( $mid_value > $low_value ) || ( $last_line_checked eq "" ) )

		{

			print "Alert\n";

		}

	}


	open ( OUTFILE, ">$checked_file" ) or die "Can't open $checked_file: $!\n";

	print OUTFILE $last_line_tempdaemon . $record_delim;

	close OUTFILE;	

}

Някои забележки:

1) Идеята е следната - сравнява се последното състояние (т.е. последния ред от tempdaemon.temp) с това от предишната проверка (което се е запазило в друг файл: tempdaemon_checked.temp).

2) Трябва да са налични нужните права за създаване/писане във въпросния файл tempdaemon_checked.temp.

3) Очаква се програмката да не се стартира преди да е приключило предишното и изпълнение.

4) Понеже се чете винаги само последния ред от tempdaemon.temp - не се анализират междинните записи след предишната проверка (ако има такива). Т.е. разни "кратки" междинни пикове може да бъдат "изпуснати".

5) При падане под критичната температура няма аларма, независимо дали критичната температура е кратна на 0.5 или не (напр. при падане от 50 на 20 при критична 27). Също няма аларма и ако се надвиши критичната температура, но без да се прескача 0.5-кратен градус (напр. при критична 37.7 и промяна от 37.6 на 37.9).

6) POSIX функцията floor, струва ми се я няма преди версия 5 на Perl, т.ч. ако си с по-ниска версия може да си я напишеш сам (или да питаш) - връща най-голямото цяло число по-малко или равно на даденото.

Ами, това е засега :) Питай, ако нещо не ти е ясно и кажи дали ще ти върши работа или да мислим нещо друго.

Редактирано от divak (преглед на промените)

  • Автор

Отново голямо благодаря! Мерси за помощта!

За съжаление не мисля, че това ще ми помогне. sad.gif

Пиковете са много важни, а и преминаването на границата също.

#!/usr/bin/perl


$critical = 27;

$lock = "temp.lock";


$string = `tail -1 tempdaemon.temp`;

($date,$time,$temp) = split(" ",$string);


if ($temp >= "$critical" && !(-f $lock)) {

  ако няма създаден файл "prowerka" създай го и запиши стойността на "$temp" в него;

  ако има - сравни актуалния "$temp" със записания във файла, и ако разликата в двете посоки е по-голяма от 0.5 - print "saob6tenie\n";, и изтрий старата стойност в "prowerka" а на нейно място запиши новата(на $temp);


  system("/usr/bin/touch $lock");

  }


if ($temp < "$critical" && -f $lock) {

  изтрий файла "prowerka";

   `/bin/rm $lock`;

  }

Това е моята представа за кода, но нямам необходимата ерудиция за да я напиша. Ако можеш да го кодираш... ех живот cool.gif .

Редактирано от Axel (преглед на промените)

OK - просто трябва да уточним какво точно ти трябва. Това, което си дал като "твоята престава за кода" по същество прави тоова, което и моето последно предложение. И страда от същия недостатък, че сравняваш "актуалната температура" с тази от предходната проверка - което означава, че пропускаш евентуални междинни температури случили се "между двете проверки"... по този начин може да изпуснеш евентуални пикове.

А това да се издава аларма при преминаването под границата не е никакъв проблем, просто ти беше посочил, че искаш сигнал, ако си над критичната (което вече не е така, щом си минал под нея ;-)).

За да изясним какво се иска ще те питам още някои неща. Да кажем, че това са температурите от последните k+1 реда във файла с температурите и че при T0 и при Tk се е изпълнил скриптът за проверка (междувременно са се случили и температурите от T1 до T(k-1), понеже /да кажем/ във файла се пише по-често отколкото се прави проверката):

T0, T1, T2, ..., Tk

В моето последно предложение (а и в твоето такова) - се проверява дали между T0 и Tk има поне една "чертичка" (чертичка значи температура кратна на 0.5 градуса) и дали Tk е над критичната.

Понеже спомена, че те интересуват и междинните пикове - кажи какво по-точно е условието за алармиране... Бих предположил следното:

1) В "критерия за аларма" да се включи преминаването на границата (в посока нагоре или надолу). Тук е хубаво да уточниш дали да има аларма, ако това преминаване е станало без "прескачане на чертичка".

2) Да се сравняват не само T0 и Tk (т.е. стойностите в момента на проверката), ами да се приложи "критерият за аларма" между T0 и всяка от температурите от T1 до Tk.

За да може да става тази проверка на междинните температури, е необходимо да може всеки ред от файла с температурите да се идентифицира уникално; това е нужно за да може да се продължи от мястото на последната проверка нататък. Сигурно ли е, например, че няма два реда във файла с еднаква дата и час? В нарастващ ред ли са записите (дата/час) във файла? И колко е голям този файл, трие ли се от време на време от него...

Алтернативно може да закачиш скрипт да следи за всяки нов ред във файла с температурите и да го подава на скрипта за проверка. Това ще ти спести ровене из файла всеки път и търсене "докъде бях стигнал предния път":

tail -1 -f /tmp/tempdaemon.temp | /wrk/bin/alarm_check.pl

Редактирано от divak (преглед на промените)

  • 3 седмици по-късно...
  • Автор

Здрасти, много благодаря за помоща!!!

Накрая "спастрих" и аз нещо. Работи безпроблемно. Обаче ми се струва малко тромавичко. Ако имаш идея как да стане по-леко, без обаче да се навреди на функционалитета, ще съм благодарско :)

#!/usr/bin/perl


$file="test.txt";

$critical=27.0;

$string = `tail -1 tempdaemon.temp`;

($date,$time,$temp) = split(" ",$temp_a);

open ( INFILE, "<$file" ) or die "Can't open $file: $!\n";

@lines = <INFILE>;

close INFILE;

$null=0.0;


if ($temp_a>=$critical){

   open ( INFILE, "<$file" ) or die "Can't open $file: $!\n";

		if ($lines[0]!=0.0){

			 $temp_t=$lines[0];

			 if($temp_a>$temp_t){

				 if(($temp_a-$temp_t)>=0.5){

					  open (OUTFILE, ">$file" ) or die "Can't open $file: $!\n";

					  print OUTFILE "$temp_a\n";

					  print "Send note with temperatur: $temp_a\n";

					  close OUTFILE;

				 }

			 }

			 if($temp_a<$temp_t){

				 if(($temp_t-$temp_a)>=0.5){

					  open (OUTFILE, ">$file" ) or die "Can't open $file: $!\n";

					  print OUTFILE "$temp_a\n";

					  print "Send note with temperatur: $temp_a\n";

					  close OUTFILE;

				 }

			 }

		}

		else{open (OUTFILE, ">$file" ) or die "Can't open $file: $!\n";

					  print OUTFILE "$temp_a\n";

					  print "Send note with temperatur: $temp_a\n";

					  close OUTFILE;

		}

   close INFILE;

}

if ($temp_a<$critical){

	 open ( INFILE, "<$file" ) or die "Can't open $file: $!\n";

	 if ($lines[0]!=0.0){

	 print "Send note with temperatur: $temp_a\n";

	 close INFILE;

	 open (OUTFILE, ">$file" ) or die "Can't open $file: $!\n";

	 print OUTFILE "$null\n";

	 close OUTFILE;

	 }

}

Не съм задлъбавал много подробно в твоята последна версия (нещо не успях да разбера откъде се взе променливата $temp_a, но предполагам, че е последният ред на tempdaemon.temp.), но като гледам логиката е такава: сравняват се текущата температура (последния ред от tempdaemon.temp) с тази от предишната проверка и се алармира, ако е мръднала с не по-малко от 0.5 градуса. Мисля, че вече обсъждахме недостатъците на подобно решение, но накратко ще спомена:

* Изпускат се пикове, ако има такива между две съседни проверки. Доколкото помня, пиковете бяха важни?

* Ако температурата расте достатъчно плавно, да кажем с 0.49 на всяка проверка - може да стигнеш и до 100 градуса, без да издадеш допълнителна аларма. Т.е. логиката в твоя вариант е аларма при достатъчно голяма скорост на промяна на температурата (>= 0.5 деления на "проверка"). А преди беше дефинирал алармата да е при пресичане на 0.5-кратни деления (независимо от скоростта на последната промяна).

Ето вариант, който мисля, че отговаря на предишните ти желания - анализират се всеки две последователни температури (от даден момент нататък). Аларма има, ако между двете температури се намира 0.5-кратно деление или пък между тях е критичната температура.

#!/usr/bin/perl

#

# temprature_monitor_v3.pl

########################################################

# Critical temperature alerter.

#

# Usage:

# (tail -f tempdaemon_file | /path/to/my/scripts/temperature_monitor_v3.pl) 2>/path/to/my/logs/tmon_err.log

#

########################################################


use POSIX qw( ceil floor );


# some constants

#

my $critical = 27.0;

my $tempdaemon_file = '/tmp/tempdaemon.temp';

my $checked_file = "/tmp/tempdaemon_checked.temp";

my $record_delim = "\n";

my $field_delim = " ";


########################################################

# get max 0.5-tick less or equal to x

#

sub get_midpoint

{

		my $x = shift;

		my $fx = floor( $x );

		my $diff = $x - $fx;

	my $result;


		if ( $diff >= 0.5 )

		{

		$result = $fx + 0.5;

		}

		else

		{

				$result = $fx;

		}


	## print "{$x; $fx; $result}\n";


	return $result;

}

########################################################


########################################################

# Given the last two records with temperature results

# analyze them and generate alert if necessary.

#

# Alarm is generated in any of the following cases:

#  1) The "critical temperature" is between the

#	 last two temperatures.

#  2) A x.50 temperature is between the last two

#	 temperatures.

#

sub analyze_and_alert

{

	my $prev_line_tempdaemon = shift;

	my $curr_line_tempdaemon = shift;


	chomp( $prev_line_tempdaemon );

	chomp( $curr_line_tempdaemon );


	## print "## Processing '$prev_line_tempdaemon' and '$curr_line_tempdaemon' (critical = $critical)\n";


	( $curr_line_tempdaemon ne "" ) or return;

	my $is_first_line = ( $prev_line_tempdaemon eq "" );


	( $date2, $time2, $temp2 ) = split( $field_delim, $curr_line_tempdaemon );


	if ( ! $is_first_line )

	{ 

		( $date1, $time1, $temp1 ) = split( $field_delim, $prev_line_tempdaemon );

	}

	else

	{

		# simulate "no-change" if this is the first iteration

		( $date1, $time1, $temp1 ) = ( $date2, $time2, $temp2 ); 

	}


	my $high_value;

	my $low_value;


	if ( $temp2 >= $temp1 )

	{

		$high_value = $temp2;

		$low_value = $temp1;

	}

	else

	{

		$high_value = $temp1;

		$low_value = $temp2;

	}


	if ( $high_value >= $critical )

	{

		my $mid_value = get_midpoint( $high_value );

		if ( ( $mid_value > $low_value ) || $is_first_line || $low_value < $critical )

		{

			print "Alert: [$prev_line_tempdaemon] - [$curr_line_tempdaemon]\n";

		}

	}

}

########################################################


########################################################

# Read each line from the standard input and perform

# an "alarm-analysis" on it.

sub main

{

	my $prev_line_tempdaemon = ""; # previous line ( N-1 )

	my $curr_line_tempdaemon = ""; # current line  ( N )


	while ( <> )

	{

		$prev_line_tempdaemon = $curr_line_tempdaemon;

		$curr_line_tempdaemon = $_;


		chomp( $prev_line_tempdaemon );

		chomp( $curr_line_tempdaemon );


		analyze_and_alert( $prev_line_tempdaemon, $curr_line_tempdaemon );

	}					

}


main();
Стартира се примерно така:
(tail -f /tmp/tempdaemon.temp | /usr/local/myscripts/temperature_monitor_v3.pl) 2>/var/log/tmon_err.log

Редактирано от divak (преглед на промените)

  • Автор

Divac, точно така - temp_a идва от темп_актуална :) . За пиковете явно не бях разбрал какво имаш предвид, но въпросните не са важни. Това е скрипт за управление не на температура, а на изпращане на съобщения. Всяка минута в tempdaemon.temp се записва новата актуална температура. Скрипта чете от него, и ако температурата скочи над 27 градуса:

1. проверява, дали във файла test.txt на първия ред стойността е 0.0, и ако е - праща съобщение, и записва актуалната температура на мястото на 0.0(примерно 27.1).

2. при следващата(след една минута) температура взета от tempdaemon.temp се проверява, дали е над 27 градуса, дали в test.txt стойността е различна от 0.0(а тя е, и в такъв случей дали е по-голяма от нея с поне 0.5 градуса. Ако да - праща съобщение, и записва новата на мястото на старата в test.txt. Ако не е по-голяма с поне 0.5 градуса, и стойността е различна от 0.0 - просто продължава нататък изпълнението на кода и не записва/праща нищо.

Така че, няма значение колко плавно се покачва температурата - новата се записва в test.txt само след сравнение със старата и само при изпълнение на определените условия. В моя пример - при записани последно 27.1 градуса в test.txt, да кажем, че температурата се покачва бавно, ще се изпрати съобщение едва когато разликата между актуалната и тази в test.txt стане равна или по-голяма от 0.5 градуса - сефте при минимум 27.6 :sobbing: . Има ли пик - примерно била е 27.1 а след една минута се докладва, че е 28.5 - то това(28.5) ще стане актуалната записана в test.txt температура, и разбира се ще се изпрати съобщение.

Пада ли - по същия начин. Особеното е, че ако температурата падне под 27.0 градуса, то първо ще провери дали в test.txt стойността е 0.0, и ако не е (това означава, че преди една минута температурата е била над 27.0 градуса) ще изпрати съобщение със актуалната температура (примерно 26.9 - да спре да се шашка админа :sobbing: ), и веднага след това ще запище в test.txt стойността 0.0.

Това, което съм направил, изпълнява перфектно каквото ми трябваше. Проблема ми вече не е във функционалността, а в оптимизацията. Кода ми е гнусен - знам, но нямам знанията за да го подобря. Ако имаш време - проследи го моля те(не е сложен - нали аз съм го писал :) ), защото отваря и затваря файла като луд, което тормози, но това е единствения начин по който успях с нищожните си познания(и в голяма степен - твоя помощ) да го накарам да прави каквото искам. Може би да създава и трие файла test.txt при преминаването на критичната? Аз това не успях да го направя.

Редактирано от Axel (преглед на промените)

OK. Наистина няма проблем с "плавното качване на температурата", не бях обърнал внимание, че в test.txt се пише само при "по-важни събития", а не всеки път. Не знам на какъв хардуер върви, но това, което си направил едва ли тормози толкоз машината, че да го оптимизираш повече. Важно е само да не се застъпват две последователни изпълнения, защото иначе не е ясно какво ще стане с test.txt... Но наистина, според мен е достатъчно да отвориш INFILE само веднъж и да го прочетеш, не знам защо го отваряш още няколко пъти. Ето ти малко съкратен вариант, който би трябвало да прави същото като твоята програмка:

#!/usr/bin/perl


$file="test.txt";

$critical=27.0;

$temp_a = `tail -1 tempdaemon.temp`;

($date,$time,$temp) = split(" ",$temp_a);

open ( INFILE, "<$file" ) or die "Can't open $file: $!\n";

@lines = <INFILE>;

close INFILE;

$null=0.0;


$temp_t = $lines[0];


if ( $temp_a >= $critical )

{

	$temp_diff = abs( $temp_a - $temp_t );

	if ( ( $temp_t == 0.0 ) || ( $temp_diff >= 0.5 ) )

	{

		open (OUTFILE, ">$file" ) or die "Can't open $file: $!\n";

		print OUTFILE "$temp_a\n";

		print "Send note with temperatur: $temp_a\n";

		close OUTFILE;

	}

}

elsif ( $temp_t != 0.0 )

{

	 print "Send note with temperatur: $temp_a\n";

	 open (OUTFILE, ">$file" ) or die "Can't open $file: $!\n";

	 print OUTFILE "$null\n";

	 close OUTFILE;

}

  • Автор
OK. Наистина няма проблем с "плавното качване на температурата", не бях обърнал внимание, че в test.txt се пише само при "по-важни събития", а не всеки път. Не знам на какъв хардуер върви, но това, което си направил едва ли тормози толкоз машината, че да го оптимизираш повече. Важно е само да не се застъпват две последователни изпълнения, защото иначе не е ясно какво ще стане с test.txt... Но наистина, според мен е достатъчно да отвориш INFILE само веднъж и да го прочетеш, не знам защо го отваряш още няколко пъти. Ето ти малко съкратен вариант, който би трябвало да прави същото като твоята програмка:

#!/usr/bin/perl


$file="test.txt";

$critical=27.0;

$temp_a = `tail -1 tempdaemon.temp`;

($date,$time,$temp) = split(" ",$temp_a);

open ( INFILE, "<$file" ) or die "Can't open $file: $!\n";

@lines = <INFILE>;

close INFILE;

$null=0.0;


$temp_t = $lines[0];


if ( $temp_a >= $critical )

{

	$temp_diff = abs( $temp_a - $temp_t );

	if ( ( $temp_t == 0.0 ) || ( $temp_diff >= 0.5 ) )

	{

		open (OUTFILE, ">$file" ) or die "Can't open $file: $!\n";

		print OUTFILE "$temp_a\n";

		print "Send note with temperatur: $temp_a\n";

		close OUTFILE;

	}

}

elsif ( $temp_t != 0.0 )

{

	 print "Send note with temperatur: $temp_a\n";

	 open (OUTFILE, ">$file" ) or die "Can't open $file: $!\n";

	 print OUTFILE "$null\n";

	 close OUTFILE;

}

divac, чудесен е, работи без грешка! Много благодаря - точно това ми трябваше!!! Имам само една идея, ако ти е лесно да я имплементираш ще е супер - файла "test.txt" да се създава при преминаване над критичната температура, и да се изтрива при преминаване под.

Пак ти казвам - голямо благодаря, без тебе едва ли щях да стигна до някъде. cool.gif

Доколкото разбирам, искаш да триеш файла, вместо да пишеш 0.0 в него (а по принцип при отваряне на файла за писане, той се създава, ако го няма):

#!/usr/bin/perl

my $file="test.txt";

my $critical=27.0;

my $null = 0.0;

my $temp_line = `tail -1 tempdaemon.temp`;


sub get_prev_temperature

{

	my $afile = shift;


	if ( -f $afile )

	{

		open ( INFILE, "<$afile" ) or die "Can't open $afile: $!\n";

		my @lines = <INFILE>;

		close INFILE;

		my $result = $lines[0];

		chomp( $result );

		return $result;

	}

	else

	{

		return $null;

	}

}


($date,$time,$temp_a) = split(" ",$temp_line);

chomp( $temp_a );

my $temp_t = get_prev_temperature( $file );


if ( $temp_a >= $critical )

{

	$temp_diff = abs( $temp_a - $temp_t );

	if ( ( $temp_t == $null ) || ( $temp_diff >= 0.5 ) )

	{

		open ( OUTFILE, ">$file" ) or die "Can't open $file: $!\n";

		print OUTFILE "$temp_a\n";

		print "Send note with temperatur: $temp_a\n";

		close OUTFILE;

	}

}

elsif ( $temp_t != $null )

{

	print "Send note with temperatur: $temp_a\n";

	unlink( $file ) or die "Can't delete $file: $!\n";

}

Добавете отговор

Можете да публикувате отговор сега и да се регистрирате по-късно. Ако имате регистрация, влезте в профила си за да публикувате от него.

Гост
Публикацията ви съдържа термини, които не допускаме! Моля, редактирайте съдържанието си и премахнете подчертаните думи по-долу. Ако замените букви от думата със звездички или друго, за да заобиколите това предупреждение, профилът ви ще бъде блокиран и наказан!
Напишете отговор в тази тема...

Разглеждащи това в момента 0

  • Няма регистрирани потребители разглеждащи тази страница.

Дарение

  • Подкрепи съществуването на форума - направи дарение
    26%
    Дарени 256.00 EUR от нужните 1,000.00 EUR

Бюлетин

Получавайте известие, когато има важна промяна или новина свързана с форума.

Профил

Навигация

Търсене

Търсене

Конфигуриране на push известия в браузъра

Chrome (Android)
  1. Докоснете иконата на катинар до адресната лента.
  2. Докоснете Разрешения → Известия.
  3. Променете предпочитанията си.
Chrome (Desktop)
  1. Кликнете върху иконата на катинар в адресната лента.
  2. Изберете Настройки на сайта.
  3. Намерете Известия и коригирайте предпочитанията си.