Seite 1 von 2

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

Verfasst: 07.10.2011 22:55
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

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

Verfasst: 08.10.2011 17:16
von remi_meier
Wie wär's mit

Code: Alles auswählen

system_("kill -2 "+str(pid))
?

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

Verfasst: 08.10.2011 19:41
von freak
Oder direkt:

Code: Alles auswählen

kill_(ProgramID(MyDD), 2)

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

Verfasst: 09.10.2011 11:54
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. :)

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

Verfasst: 30.12.2013 03:06
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

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

Verfasst: 30.12.2013 12:43
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)

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

Verfasst: 30.12.2013 19:36
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!

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

Verfasst: 30.12.2013 19:53
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.

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

Verfasst: 31.12.2013 14:49
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?

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

Verfasst: 31.12.2013 14:58
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.