Control + C an mit RunProgram() geöffnetes Programm senden

In dieser Linux-Ecke dürfen nur Themen rund um Linux geschrieben werden.
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
sleepyhead
Beiträge: 13
Registriert: 31.01.2006 01:03
Wohnort: Mettendorf TG (Schweiz)

Control + C an mit RunProgram() geöffnetes Programm senden

Beitrag von sleepyhead »

Hallo,

Ich bin darauf und daran eine Festplatte wiederherzustellen, bei welcher immer wieder die Kommunikation zusammenbricht, beziehungsweise /dev/sdb verloren geht. Nachdem /dev/sdb verloren geht, beendet sich dd_rescue leider nicht, sondern meldet einfach für jeden weiteren Block einen Fehler. Mit Control + C kann ich es manuell stoppen und es schreibt das Log fertig. Wenn ich es mit RunProgram() in Purebasic ausführe, kann ich es mit KillProgram() beenden, allerdings schreibt es in diesem Fall die Logdatei nicht fertig und meine letzte Position ist so nicht vermerkt. Folgendes habe ich ausprobiert, um es schön zu beenden, allerdings wird das "^C" leider nicht als Control + C erkannt. Gibt es eine Möglichkeit dem Programm anders mitzuteilen, dass es sich beenden soll? Folgend der ganze Code:

Code: Alles auswählen

InitNetwork()

Procedure.s getLastPos()
  ; Liest die letzte Position aus dem Logfile aus
  Dim arrFound.s(1)
  If ReadFile(0, "/home/sleepyhead/400gb.log")
    FileSeek(0, Lof(0)-1000)
    fountIt = 0
    Repeat
      Text$ = ReadString(0)
      If FindString(Text$, "ipos:") And FindString(Text$, ", opos:")
        If CreateRegularExpression(0, "[0-9]+\.[0-9]k")
          ExtractRegularExpression(0, Text$, arrFound())
          FreeRegularExpression(0)
        Else
          PrintN("Error: "+RegularExpressionError())
        EndIf
        lastPos$ = arrFound(0)
        fountIt = 1
      EndIf
      Delay(1)
    Until fountIt = 1 Or Eof(0)
    CloseFile(0)
  EndIf
  If lastPos$ = "" : lastPos$ = "0.0k" : EndIf
  ProcedureReturn  lastPos$
EndProcedure

OpenConsole()

; Prüft und mounted gegebenfalls /mnt/transfer, wo das dd-File hin soll
If ReadFile(0, "/mnt/transfer/400gb.dd")
  CloseFile(0)
Else
  RunProgram("mount", "/mnt/transfer", "/usr/bin/" ,#PB_Program_Wait)
  If ReadFile(0, "/mnt/transfer/400gb.dd")
    CloseFile(0)
    PrintN("/mnt/transfer mounted!")
  Else
    PrintN("Can't mount /mnt/transfer!")
    End
  EndIf
EndIf

MyDD = RunProgram("dd_rescue", "-s "+getLastPos()+" -l /home/sleepyhead/400gb.log -o /home/sleepyhead/400gbBB.log /dev/sdb /mnt/transfer/400gb.dd", "/home/sleepyhead", #PB_Program_Open|#PB_Program_Read|#PB_Program_Write)

If IsProgram(MyDD)
  Repeat
    If ProgramRunning(MyDD)
      If ReadFile(0, "/dev/sdb") = 0
        ; hier versuche ich erfolglos das Programm zu beenden
        WriteProgramStringN(MyDD, "^C")
        While ProgramRunning(MyDD)
          Delay(1)
        Wend
        CloseProgram(MyDD)
        ; Danach wird über ein Netzwerkschalter der Strom zur Festplatte für fünf Sekunden unterbrochen
        ReceiveHTTPFile("http://192.168.6.9/ips.cgi?pg=ips&Aus=Aus", "~/lastipsstate")
        Delay(5000)
        ReceiveHTTPFile("http://192.168.6.9/ips.cgi?pg=ips&Ein=Ein", "~/lastipsstate")
        ; Sobald die Festplatte wieder sichbar ist, führe ich erneut dd_rescue aus
        Repeat
          Delay(1000)
        Until ReadFile(0, "/dev/sdb")
        CloseFile(0)
        MyDD = RunProgram("dd_rescue", "-s "+getLastPos()+" -l /home/sleepyhead/400gb.log -o /home/sleepyhead/400gbBB.log /dev/sdb /mnt/transfer/400gb.dd", "/home/sleepyhead", #PB_Program_Open|#PB_Program_Read|#PB_Program_Write)
      Else
        CloseFile(0)
      EndIf
    Else
      PrintN("dd_rescue not running!")
      CloseConsole()
      End
    EndIf
    Delay(1)
  ForEver
EndIf

CloseConsole()
Gruss
sleepyhead
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Re: Control + C an mit RunProgram() geöffnetes Programm send

Beitrag von remi_meier »

Wie wär's mit

Code: Alles auswählen

system_("kill -2 "+str(pid))
?
freak
PureBasic Team
Beiträge: 766
Registriert: 29.08.2004 00:20
Wohnort: Stuttgart

Re: Control + C an mit RunProgram() geöffnetes Programm send

Beitrag von freak »

Oder direkt:

Code: Alles auswählen

kill_(ProgramID(MyDD), 2)
sleepyhead
Beiträge: 13
Registriert: 31.01.2006 01:03
Wohnort: Mettendorf TG (Schweiz)

Re: Control + C an mit RunProgram() geöffnetes Programm send

Beitrag von sleepyhead »

Vielen Dank für eure Antwort remi_meier und freak. Die direkte Methode von freak habe ich nun im Programm integriert und die läuft perfekt. :)
Wolfram
Beiträge: 28
Registriert: 23.08.2013 14:38
Computerausstattung: OSX 10.13 | PB 5.46

Re: Control + C an mit RunProgram() geöffnetes Programm send

Beitrag von Wolfram »

Hallo,

ich habe ein ähnliches Problem. Ich möchte ctrl + T an ein geöffnetes Programm senden, um zu sehen wie weit der Vorschritt von dd ist.
Kann mir jemand sagen wie das geht?

Gruß

Wolfram
OSX 10.13 | PB 5.46
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8677
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Control + C an mit RunProgram() geöffnetes Programm send

Beitrag von NicTheQuick »

Eigentlich ganz einfach. Man schaut zunächst welches Signal das sein soll, was 'dd' dazu bewegt den aktuellen Status auszugeben. Das findet man in der Manpage.
man dd hat geschrieben:Sending a USR1 signal to a running 'dd' process makes it print I/O statistics to standard error and then resume copying.
Also ist es das Signal USR1. Dann sucht man den genauen Signalnamen bzw. dessen Nummer mit 'kill -l':

Code: Alles auswählen

 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX
Also heißt das Signal wohl SIGUSR1 und hat die Nummer 10.
Angewendet auf freaks Methode wäre das also:

Code: Alles auswählen

kill_(ProgramID(MyDD), 10)
Bild
Wolfram
Beiträge: 28
Registriert: 23.08.2013 14:38
Computerausstattung: OSX 10.13 | PB 5.46

Re: Control + C an mit RunProgram() geöffnetes Programm send

Beitrag von Wolfram »

Hi,

danke für den Tipp.
Das Problem ist nur dass, das ReadProgramString nichts ausspuckt.
kannst Du mir ein Beispiel Code tippen?

Danke!
OSX 10.13 | PB 5.46
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8677
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Control + C an mit RunProgram() geöffnetes Programm send

Beitrag von NicTheQuick »

Das liegt daran, dass 'dd' den Status nicht über den Standard Output ausgibt, sondern über den Error Output.
man dd hat geschrieben:Sending a USR1 signal to a running 'dd' process makes it print I/O statistics to standard error and then resume copying.
Du musst also 'ReadProgramError()' nutzen.
Bild
Wolfram
Beiträge: 28
Registriert: 23.08.2013 14:38
Computerausstattung: OSX 10.13 | PB 5.46

Re: Control + C an mit RunProgram() geöffnetes Programm send

Beitrag von Wolfram »

Hi,

das klappt danke!

Habe aber noch ein Problem. Wenn der Dateipfad für das Diskimage ein space beinhaltet funktioniert der Befehl nicht mehr.
Egal ob ich "/my image.img" oder "/my\ image.img" schreibe.

Code: Alles auswählen

RunProgram("/bin/dd", "if=/my\ image.img of=/dev/disk1 bs=1m", "", #PB_Program_Open
Hast Du da auch eine Lösung?
OSX 10.13 | PB 5.46
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Control + C an mit RunProgram() geöffnetes Programm send

Beitrag von ts-soft »

Probier mal:

Code: Alles auswählen

RunProgram("/bin/dd", "if=" + #DQUOTE$ + "/my\ image.img" + #DQUOTE$ + " of=/dev/disk1 bs=1m", "", #PB_Program_Open 
Der Backslash maskiert das Leerzeichen ja nur für die Bash. Die #DQUOTE$ sollten den Parameter zusammenhalten.
Kann auch sein, daß das Backslash nicht benötigt wird, einfach probieren.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Antworten