Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: petrusic - Luglio 09, 2022, 07:26:18 pm

Titolo: [Risolto] avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: petrusic - Luglio 09, 2022, 07:26:18 pm
Rendere chiaro ed autoesplicativo il titolo di una discussione, diventa volte un'impresa insormontabile.
Cerco di spiegare qui quello che vorrei ottenere:

Ho terminato una parte del mio programma DomusRatio. Ho anche cristallizzato il file eseguibile (DomusRatio.Lazarus), in modo che posso avviare sempre l'attuale programma, funzionante e, poichè il mio ambiente Linux è avviabile in DualBoot (Ubuntu e Fedora), ho creato due file DomusRatio.desktop, uno in ciascun ambiente operativo, in modo che posso lanciare quell'eseguibile sempre, a prescindere se sto usando Fedora o Ubuntu.

Nella mia logica, fin qui funziona tutto bene.

Ho scoperto però che occorrerebbero le seguenti protezioni:

a)- Avviare solo una volta l'eseguibile, cioè, impedire  che, dopo avere avviato l'eseguibile la prima volta, se mentre esso è attivo, clicco di nuovo sull'icona, si avvii una seconda volta, poi una terza e . . . così via fino ad avere attive, tutte in esecuzione, n copie dello stesso programma.

b)- Evitare ancora di ripetere ad ogni avvio la produzione automatica di una copia di salvataggio del relativo Database se fra la prima e la seconda volta non è passato almeno un giorno.

la protezione a) dovrebbe essere generata dall'uso del comando
Codice: [Seleziona]
pidof DomusRatio.Lazarus
a.1) se il programma NON è attivo : non restituisce niente
a.2) se il programma è attivo, restituisce :
Codice: [Seleziona]
$ pidof DomusRatio.Lazarus
4591

la protezione b) dovrebbe essere di non difficile soluzione, sfruttando opportunamente il comando 
Codice: [Seleziona]
debugfs -R 'stat <inode_number>' /dev/sdb1
relativo al file da interrogare.

Ora, se non avete altre indicazioni, non mi resta che modificare il programma per comprendervi i comandi suddetti

Titolo: Re:avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: DragoRosso - Luglio 10, 2022, 10:25:25 am
Ciao,
alternative a ciò che hai proposto, in Linux effettivamente non è che ce ne siano molte.

* Per il controllo di singola istanza (a) come alternativa, che è la più usata, è aprire e fare un lock su un file (ad esempio DomusRatio.once). Tutte le istanze dell'applicazione tentano di fare il lock sul file e solo la prima che ci riesce "girerà", le eventuali altre si chiuderanno.

Per la (b), dovrebbe esserci una funzione di sistema operativo che ti ritorna le proprietà di un file (ad esempio data e ora di creazione, modifica, etc ...). C'è sotto Windows, non sono sicuro sotto Linux.

Io sinceramente non mi fido molto dei risultati delle utility a riga di comando, già in passato ho avuto problemi con i vari formati di date dei vari paesi (faccio applicazioni prevalentemente internazionali, e tra virgole, punti, giorno /mese è già un piangere).

Ciao

* AGGIORNAMENTO: non è così semplice fare il lock in Linux, perchè Linux è nato senza implementazione del LOCK per ragioni di prestazioni.

Esistono a livello di script i comandi LOCK, ISLOCKS e FLOCK (tutti in minuscolo ovviamente) ma non ci sono delle API relative (almeno non le ho trovate). Inoltre il filesystem deve essere montato con delle particolari opzioni.

Non sono un esperto di Linux, questo lo si sà, ma ciò mi ha un attimo "scosso" .... :o
Titolo: Re:avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: bonmario - Luglio 10, 2022, 02:36:55 pm
Ciao, per quanto riguarda il quesito a) potresti usare questo: https://wiki.freepascal.org/UniqueInstance io non l'ho mai fatto, perché ho scoperto tardi che esisteva, ed uso un metodo simile a quello che hai scritto tu.
Per quanto riguarda invece il quesito b), puoi fare tutto da Lazarus, senza scomodare il sistema operativo:
Codice: [Seleziona]
const CstConvDataErr=-1;


  function  DataUltimaModifica(const NomeFile:String):TDateTime;
  var DataFile:Longint;
  begin
    DataFile:=FileAgeUTF8(NomeFile);

    //In caso di file non trovato, DataFile vale -1
    if (DataFile = -1) then begin
      Result:=CstConvDataErr;
    end else begin
      UnixToDateTime(UnixFileTime);
    end;
  end;

Devi aggiungere alla uses "dateutils e LazFileUtils". La funzione riceve in input il nome del file, e restituisce la data di ultima modifica di tale file.

Usando poi l'istruzione DaysBetween, puoi verificare quanti giorni di difeerenza ci sono tra oggi e tale data

Ciao, Mario
Titolo: Re:avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: petrusic - Luglio 10, 2022, 10:48:07 pm
per quanto riguarda il quesito a) potresti usare questo: https://wiki.freepascal.org/UniqueInstance

Ho seguito il tuo consiglio, però non credo di avere capito come usarlo, infatti, all'avvio ricevo il seguente messaggio d'errore:
Citazione
Il progetto DomusRatio ha sollevato una eccezione di classe 'External: SIGSEGV'.

 All'indirizzo 420A40

Ecco come ho proceduto:
,

Non ho impostato la proprietà Identificatore:
Non ho scritto la chiamata alla funzione InstanceRunning (nella guida non è spiegato come dovrei procedere)

Come avrai intuito, non ho scritto una riga di codice, quindi non ho riportato niente qui.

Capisco che non hai mai usato il componente "uniqueinstance", ma conosci bene l'ambienteLazarus FreePascal, mentre io devo fermarmi ad ogni passo per capire, applicare, capire di nuovo dove ho sbagliato ed assimilare le correzioni necessarie.
Titolo: Re:avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: bonmario - Luglio 11, 2022, 08:03:03 am
Mi spiace, ma non ti so aiutare, se mastichi l'inglese, potresti chiedere sul forum internazionale.
Gli unici consigli che ti posso dare, sono quelli generici:
- caricare l'ultima versione di Lazarus
- caricare l'ultima versione del componente

P.S. Anche la soluzione che avevi trovato tu va bene, se per te è più semplice quella, usa quella. Magari fai una funzione apposta da richiamare quando ti serve, così se un domani volessi cambiarne il funzionamento, ti basterà modificare il contenuto di tale funzione e, tutti i programmi che la chiamano andranno solo ricompilati.

Ciao, Mario
Titolo: Re:avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: DragoRosso - Luglio 11, 2022, 10:12:23 am
Ciao.
Ho fatto una prova con Lazarus 2.2.2 e fpc 3.2.2

A me funziona senza problema alcuno (sotto Windows).

L'evento viene "scatenato" SULLA PRIMA ISTANZA dell'applicazione quando un'altra istanza viene lanciata.

PROVE EFFETTUATE SOTTO WINDOWS, NON HO LINUX A DISPOSIZIONE IN QUESTI GIORNI.

Ciao ciao
Titolo: Re:avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: petrusic - Luglio 11, 2022, 10:48:52 am
Ho fatto una prova con Lazarus 2.2.2 e fpc 3.2.2
A me funziona senza problema alcuno (sotto Windows).

Ti ringrazio, ma avendo debellato dalla mia mente Windows tanti anni fa, dispongo solo di Linux ed a volte mi ingarbuglio nei suoi meandri, per me non facili da percorrere.

In ogni caso ci sarebbe la proprietà "UpdateInterval (1000)", che non mi risulta comprensibile nel risultato pratico. Sembrerebbe, a naso, che, in ambiente Linux, il controllo della presenza attiva unica del programma corrente termini dopo soli 1000 ms, mentre, secondo me dovrebbe essere mantenuta per tutto il tempo in cui il programma corrente rimane attivo.

Penso perciò di riprendere il controllo artigianale che avevo scritto prima di scoprire l'esistenza di "uniqueinstance" .
Titolo: Re:avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: petrusic - Luglio 11, 2022, 11:56:51 am
Mi spiace, ma non ti so aiutare, se mastichi l'inglese, potresti chiedere sul forum internazionale.
. . .

P.S. Anche la soluzione che avevi trovato tu va bene, se per te è più semplice quella, usa quella. Magari fai una funzione apposta da richiamare quando ti serve, così se un domani volessi cambiarne il funzionamento, ti basterà modificare il contenuto di tale funzione e, tutti i programmi che la chiamano andranno solo ricompilati.

Si, riprendere la mia idea potrebbe essere una soluzione. Dovrei però superare due ostacoli:
- fare partire il controllo prima che compaia la Form1 a video;
- Individuare e superare l'errore di eccezione che ricevo all'avvio del programma:
Citazione
Il progetto DomusRatio ha sollevato una eccezione di classe 'EProcess' con messaggio:
Executable not found: "pidof DomusRatio.Lazarus >  /media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/bin/file_pidof".
All'indirizzo 714BD4
L'errore si manifesta all'esecuzione dell'istruzione  evidenziata nel gruppo Aprocess seguente:
Codice: [Seleziona]
procedure TForm1.FormCreate(Sender: TObject);
const
  meno: Char = '-';

var
  AProcess: Tprocess;

  striMia: String;

begin                                                                         
  percorso := ExtractfilePath(Application.ExeName);
  striMia:= 'pidof DomusRatio.Lazarus ' + Chr(62) + ' ' + percorso + 'file_pidof';
  AProcess := Tprocess.Create(nil); // costruttore (Crea una nuova istanza della classe TProcess)
  AProcess.Executable:= striMia;
  AProcess.Options := AProcess.Options + [poWaitOnExit]; // l’opzione [poWaitOnExit] fa si che il programma corrente riprenda il suo percorso soltanto dopo che il comando pidof sarà terminato

  Aprocess.Execute;      <<---------- ERRORE ERRORE ERRORE

  Aprocess.Free; //  conclude logicamente il processo appena terminato, liberando l’area di memoria impegnata durante l’esecuzione

  ShowMessage('leggi "file_pidof"');
Titolo: Re:avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: DragoRosso - Luglio 11, 2022, 12:02:38 pm
Ho ripreso possesso di un Linux ... fuori linea per un problema con il GARR (ieri il proxy del GARR è andato "GIU"  :o ).

Ho fatto la prova compilando lo stesso progetto Windows -> LINUX X86-X64 con il cross compiler (da Windows x64).

L'eseguibile lanciato in un server Linux Ubuntu 22.04 LTS x64 Intel ha funzionato senza problemi.

Server, tra l'altro con solo una shell grafica (LXQT) e la libreria "libncurses5", nessun altro pacchetto aggiunto.

Appena possibile farò una prova anche con un Ubuntu 20.04 e un 16.04.


In ogni caso ci sarebbe la proprietà "UpdateInterval (1000)", che non mi risulta comprensibile nel risultato pratico. Sembrerebbe, a naso, che, in ambiente Linux, il controllo della presenza attiva unica del programma corrente termini dopo soli 1000 ms, mentre, secondo me dovrebbe essere mantenuta per tutto il tempo in cui il programma corrente rimane attivo.

Il valore UpdateInterval determina (dovrebbe determinare... da quello che ho capito) la frequenza di controllo dei "messaggi" IPC relativi alla presenza di ulteriori istanze (quello che genera praticamente l'evento nella prima istanza).

L'istanza ulteriore "termina" subito, ma probabilmente per andare a catturare il messaggio relativo all'IPC e segnalare alla prima istanza che una ulteriore è stata lanciata è necessario un poling ... UpdateInterval determina il tempo di polling.

L'IPC è una tecnica di comunicazione tra processi (Inter Process Comunication): https://it.wikipedia.org/wiki/Comunicazione_tra_processi (https://it.wikipedia.org/wiki/Comunicazione_tra_processi)

Tale tecnica, basata su tecnologia prevalentemente CLIENT / SERVER, consente di condividere dati tra due processi in maniera "standard" anche tra sistemi operativi diversi.

Ciao
Titolo: Re:avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: bonmario - Luglio 11, 2022, 12:26:45 pm
Citazione

Si, riprendere la mia idea potrebbe essere una soluzione. Dovrei però superare due ostacoli:
- fare partire il controllo prima che compaia la Form1 a video;
- Individuare e superare l'errore di eccezione che ricevo all'avvio del programma:
Citazione
Il progetto DomusRatio ha sollevato una eccezione di classe 'EProcess' con messaggio:
Executable not found: "pidof DomusRatio.Lazarus >  /media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/bin/file_pidof".
All'indirizzo 714BD4
L'errore si manifesta all'esecuzione dell'istruzione  evidenziata nel gruppo Aprocess seguente:

Stai usando le istruzioni in maniera errata ... dai un occhio qui:
https://wiki.freepascal.org/Executing_External_Programs#Reading_large_output


Prendi il codice che c'è lì dentro e mettilo in un progetto nuovo di test. Una volta che ne capisci il funzionamento, sarà una stupidata adattarlo alle tue esigenze col comando pidof

Ciao, Mario
Titolo: Re:avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: petrusic - Luglio 11, 2022, 10:09:47 pm
Vi ringrazio per i vostri suggerimenti.

Tuttavia, visto che ho difficolta' con gli strumenti Lazarus e visto che non riesco a fare funzionare nel mio programma il comando pidof, ho optato per una terza soluzione, inserendo l'avvio del programma DomusRatio in uno script che ho scritto oggi.

Allo stesso script ho affidato l'uso del comando pidof reindirizzandone l'output su un file che interrogo subito dopo per sapere se l'applicativo è già attivo. Funziona benissimo e mi posso accontentare così.

Riporto,, per completezza, lo script che ho preparato e provato:
Codice: [Seleziona]
#!/bin/bash
# Script 'domusratio.sh' di:
# avvio del programma di CONTABILITA' FAMILIARE
# ---------------------------------------------------
# scritto il 11-luglio-2022
#-------
clear
echo "Sono le ore $(date +%k)":"$(date +%M)"
echo "----------------------------"
#---variabili
destin="/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/bin/file_pidof"
let n=0
record=
#---
pidof DomusRatio.Lazarus > $destin
while read record
do
    ((n += 1))
done < $destin   
# echo "record letti= $n"
{
if [ $n = 0 ]
then
"/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/bin/DomusRatio.Lazarus"
fi
}
exit 0

Purtroppo ho l'obbligo di avviarlo da terminale shell, ma sono sicuro di avviar il programma soltanto dopo avere accertato che non è attivo.

Ora mi resta soltanto di evitare la produzione di una copia del DB automatica all'avvio del programma, entro un certo intervallo di tempo dalla precedente.
Titolo: Re:avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: nomorelogic - Luglio 12, 2022, 11:53:31 am
Ora mi resta soltanto di evitare la produzione di una copia del DB automatica all'avvio del programma, entro un certo intervallo di tempo dalla precedente.

per questo puoi partire da qua
Codice: [Seleziona]
for myfile in *.iso; do echo echo $myfile = $((($(date +%s) - $(date +%s -r "$myfile")) / 86400)) days; done
Titolo: Re:avviare NomeProgramma.Lazarus da un S.O Linux diverso
Inserito da: petrusic - Luglio 12, 2022, 05:49:27 pm
Ora mi resta soltanto di evitare la produzione di una copia del DB automatica all'avvio del programma, entro un certo intervallo di tempo dalla precedente.

Ho risolto dopo che la notte ha portato consiglio.

L'opzione di eseguire una copia automatica giornaliera, al massimo, non mi è sembrata una buona idea, perchè si potrebbero verificare condizioni, per cui si debba eseguire la copia, anche più volte in un giorno, oppure non farne per più giorni.
Ho allora deciso di lasciare decidere all'utilizzatore stesso, attraverso una finestra di dialogo di tipo QuestionDlg.
Ho fatto la modifica, ho provato e sono soddisfatto.

Grazie e a tutti. ;D