Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem Služba v C# - NET otázka ohledně stability služby

Dobrý den,

potřebuji nutně konzultovat službu.
Služba se periodicky dotazuje databáze a je nezbytné, aby fungovala jednou a korektně.
Je napsaná v .NET C#

Účelem je spustit PHP skript, který spustí následně program B, který trvá různou dobu.
Jakmile se spuštěný program B dokončí, je žádoucí, aby služba zafungovala znovu a program B opět spustila.
A tento program B fungoval opět nějakou dobu.

Funguje to ovšem pouze nějakou dobu skvěle, ale pak program B přestane korektně pracovat.
Žádoucí je, aby nikdy nedošlo ke dvojitému spuštění programu B.

Bohužel se stává něco nežádoucího, kdy spuštěný program B kolabuje.

Poměrně jednoduchá služba:

 
public class ServiceImplementation : IWindowsService
 {
  private static Timer Timer;
        
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        public void Dispose()
        {
            Timer.Stop();
        }

        /// <summary>
        /// This method is called when the service gets a request to start.
        /// </summary>
        /// <param name="args">Any command line arguments</param>
        public void OnStart(string[] args)
        {
            Timer = new Timer(2000); // every 2 seconds
            Timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
            Timer.Start(); // <- important

        }

        private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (Timer.Enabled == true)
                Timer.Stop();
           
            
            ProcessStartInfo start = new ProcessStartInfo();
            // Enter in the command line arguments, everything you would enter after the executable name itself
            start.Arguments = "-f c:\\Programy\\EasyPHP-Devserver-17\\eds-www\\program.php";
            // Enter the executable to run, including the complete path
            start.FileName = @"C:\Programy\EasyPHP-Devserver-17\eds-binaries\php\php5630vc11x86x200506203219\php.exe";
            // Do you want to show a console window?
            start.WindowStyle = ProcessWindowStyle.Hidden;
            start.CreateNoWindow = true;
            int exitCode;


            // Run the external process & wait for it to finish
            using (Process proc = Process.Start(start))
            {
                proc.WaitForExit();
                // Retrieve the app's exit code
                exitCode = proc.ExitCode;
            }

           
            if( Timer.Enabled == false)
            Timer.Start();
        }

        /// <summary>
        /// This method is called when the service gets a request to stop.
        /// </summary>
        public void OnStop()
        {
            
            Timer.Stop();
        }

        /// <summary>
        /// This method is called when a service gets a request to pause,
        /// but not stop completely.
        /// </summary>
        public void OnPause()
        {
            
            Timer.Stop();
        }

        /// <summary>
        /// This method is called when a service gets a request to resume 
        /// after a pause is issued.
        /// </summary>
        public void OnContinue()
        {
            
            Timer.Start();
        }

        /// <summary>
        /// This method is called when the machine the service is running on
        /// is being shutdown.
        /// </summary>
        public void OnShutdown()
        {
            Timer.Stop();
        }

Vidí tady někdo nějaký problém, který zapřičiní, že se program B (ve skriptu program.php) může spustit vícekrát ?
Případně nějaký Fix ?

Děkuji mnohokrát, klidně doplním případné info.

Předmět Autor Datum
A kolabuje protože se spouští dvakrát?
Wikan 07.08.2023 22:53
Wikan
Program nazvaný program B, který spouští PHP skript se nesmí spustit 2x ve stejném čase. Přesný důvo…
Flash_Gordon 07.08.2023 22:56
Flash_Gordon
Na prvni pohled nevidím důvod, proč by se to mělo spustit dvakrát.
Wikan 07.08.2023 23:06
Wikan
Dobře. A mohu se zeptat doplňující otázku, přes jaký software by ses připojoval přes telnet skrze PH…
Flash_Gordon 07.08.2023 23:18
Flash_Gordon
No já bych to hlavně nedělal pomocí PHP. poslední
Wikan 08.08.2023 07:31
Wikan
Podle me ti to php.exe vrati exit code, i kdyz script (program.php) jeste bezi (udelal mu pro beh in…
PureXena 07.08.2023 23:03
PureXena
Zabuduj si do programu B jednoduchy semafor. Na zatatku spusteni programu se zapise do nejake tabulk…
Jan Fiala 08.08.2023 05:42
Jan Fiala

Program nazvaný program B, který spouští PHP skript se nesmí spustit 2x ve stejném čase.
Přesný důvod kolabsu mi bohužel není znám.

Tak se ptám, jestli je ve službě nebezpečí, že to spustí 2x ve stejný čas (kdy první instance programu B "ještě" běží).

Teda takto program B se přes putty někam připojí a něco dělá.
A nesmí se připojovat na zařízení 2x, protože nepodporuje dvojité přihlášení.

Dobře. A mohu se zeptat doplňující otázku, přes jaký software by ses připojoval přes telnet skrze PHP?

Já používám k připojení starší knihovnu https://www.geckotribe.com/php-telnet/

class PHPTelnet {
	var $show_connect_error=1;

	var $use_usleep=0;	// change to 1 for faster execution
		// don't change to 1 on Windows servers unless you have PHP 5
	var $sleeptime=65;
	var $loginsleeptime=10;

	var $fp=NULL;
	var $loginprompt;

	var $conn1;
	var $conn2;
	
	/*
	0 = success
	1 = couldn't open network connection
	2 = unknown host
	3 = login failed
	4 = PHP version too low
	*/
	function Connect($server,$user,$pass) {
		$rv=0;
		$vers=explode('.',PHP_VERSION);
		$needvers=array(4,3,0);
		$j=count($vers);
		$k=count($needvers);
		if ($k<$j) $j=$k;
		for ($i=0;$i<$j;$i++) {
			if (($vers[$i]+0)>$needvers[$i]) break;
			if (($vers[$i]+0)<$needvers[$i]) {
				$this->ConnectError(4);
				return 4;
			}
		}
		
		$this->Disconnect();
		
		if (strlen($server)) {
			if (preg_match('/[^0-9.]/',$server)) {
				$ip=gethostbyname($server);
				if ($ip==$server) {
					$ip='';
					$rv=2;
				}
			} else $ip=$server;
		} else $ip='127.0.0.1';
		
		if (strlen($ip)) {
			if ($this->fp=fsockopen($ip,2323)) {
				fputs($this->fp,$this->conn1);
				$this->Sleep();
				
				fputs($this->fp,$this->conn2);
				$this->Sleep();
				$this->GetResponse($r);
				$r=explode("\n",$r);
				$this->loginprompt=$r[count($r)-1];

				fputs($this->fp,"$user\r");
				$this->Sleep();

				fputs($this->fp,"$pass\r");
				if ($this->use_usleep) usleep($this->loginsleeptime);
				else sleep(1);
				$this->GetResponse($r);
				$r=explode("\n",$r);
				if (($r[count($r)-1]=='')||($this->loginprompt==$r[count($r)-1])) {
					$rv=3;
					$this->Disconnect();
				}
			} else $rv=1;
		}
		
		if ($rv) $this->ConnectError($rv);
		return $rv;
	}
	
	function Disconnect($exit=1) {
		if ($this->fp) {
			if ($exit) $this->DoCommand('exit',$junk);
			fclose($this->fp);
			$this->fp=NULL;
		}
	}

	function DoCommand($c,&$r) {
		if ($this->fp) {
			fputs($this->fp,"$c\r");
			$this->Sleep();
			$this->GetResponse($r);
			$r=preg_replace("/^.*?\n(.*)\n[^\n]*$/","$1",$r);
		}
		return $this->fp?1:0;
	}
	
	function GetResponse(&$r) {
		$r='';
		do { 
			$r.=fread($this->fp,8000);
			$s=socket_get_status($this->fp);
		} while ($s['unread_bytes']);
	}
	
	function Sleep() {
		if ($this->use_usleep) usleep($this->sleeptime);
		else sleep(1);
	}
	
	function PHPTelnet() {
		$this->conn1=chr(0xFF).chr(0xFB).chr(0x1F).chr(0xFF).chr(0xFB).
			chr(0x20).chr(0xFF).chr(0xFB).chr(0x18).chr(0xFF).chr(0xFB).
			chr(0x27).chr(0xFF).chr(0xFD).chr(0x01).chr(0xFF).chr(0xFB).
			chr(0x03).chr(0xFF).chr(0xFD).chr(0x03).chr(0xFF).chr(0xFC).
			chr(0x23).chr(0xFF).chr(0xFC).chr(0x24).chr(0xFF).chr(0xFA).
			chr(0x1F).chr(0x00).chr(0x50).chr(0x00).chr(0x18).chr(0xFF).
			chr(0xF0).chr(0xFF).chr(0xFA).chr(0x20).chr(0x00).chr(0x33).
			chr(0x38).chr(0x34).chr(0x30).chr(0x30).chr(0x2C).chr(0x33).
			chr(0x38).chr(0x34).chr(0x30).chr(0x30).chr(0xFF).chr(0xF0).
			chr(0xFF).chr(0xFA).chr(0x27).chr(0x00).chr(0xFF).chr(0xF0).
			chr(0xFF).chr(0xFA).chr(0x18).chr(0x00).chr(0x58).chr(0x54).
			chr(0x45).chr(0x52).chr(0x4D).chr(0xFF).chr(0xF0);
		$this->conn2=chr(0xFF).chr(0xFC).chr(0x01).chr(0xFF).chr(0xFC).
			chr(0x22).chr(0xFF).chr(0xFE).chr(0x05).chr(0xFF).chr(0xFC).chr(0x21);
	}
	
	function ConnectError($num) {
		if ($this->show_connect_error) switch ($num) {
		case 1: echo '<br />[PHP Telnet] <a href="http://www.geckotribe.com/php-telnet/errors/fsockopen.php">Connect failed: Unable to open network connection</a><br />'; break;
		case 2: echo '<br />[PHP Telnet] <a href="http://www.geckotribe.com/php-telnet/errors/unknown-host.php">Connect failed: Unknown host</a><br />'; break;
		case 3: echo '<br />[PHP Telnet] <a href="http://www.geckotribe.com/php-telnet/errors/login.php">Connect failed: Login failed</a><br />'; break;
		case 4: echo '<br />[PHP Telnet] <a href="http://www.geckotribe.com/php-telnet/errors/php-version.php">Connect failed: Your server\'s PHP version is too low for PHP Telnet</a><br />'; break;
		}
	}
}

return;
?>

Zabuduj si do programu B jednoduchy semafor. Na zatatku spusteni programu se zapise do nejake tabulky/souboru ze program bezi, na konci program zapise, ze skoncil.
Sluzba se koukne a pokud B neskoncil, bude cekat, po nejake dobe pak bude informovat, ze B se zase seknul

Zpět do poradny Odpovědět na původní otázku Nahoru