Shellskript nur einmal ausführen

L I V E Stammtisch ab 20:30 Uhr im Chat
  • Hallo,

    ich habe da ein kleines Problem bei meiner kleinen spielerei die ich hier versuche.
    Und zwar folgendes Szenario.
    Ich habe daheim eine Klingelanlage aus einem Pi und einem 433 MHz Funksender gebaut.
    Bei betätigen des Funksenders wird ein MP3 File abgespielt.
    Jetzt will ich per Tablet bzw Handy auch noch Texte abspielen können (ich habe daheim
    ein kleines Tonstudio da macht sich das ganz gut).
    Ich habe das ganze per LAN, nem Apache 2 Server und ner PHP Seite, von der aus ich shellskripte aufrufe, realisiert.
    Das klappt auch ganz gut, also ich gehe auf dem Tablet auf die Webseite, die sich auf meinem Apache
    Server befindet, tippe auf den gewünschten Text und im Regieraum wird er dann abgespielt.

    Jetzt kommt aber das Problem, wenn ich einen Text ausversehen 2 oder mehrmals antippe,
    startet der Text auch mehrmals und die Texte überschneiden sich auch noch.
    Dies hört sich echt bescheiden an und nervt einfach nur, da mir das relativ häufig passiert.

    Gibt es eine Möglichkeit dies zu unterbinden ?

    Ich hab bis jetzt leider nichts gefunden.
    Evtl kann man der Soundkarte ja sagen sie soll nur ein File abspielen.
    Meine Klingel läuft über ein Pythonskript, da habe ich sollche probleme nicht.

    Ich hoffe ich konnte mich halbwegs verständlich ausdrücken.

    Gruß

    Martin

    Einmal editiert, zuletzt von skull2505 (25. Juni 2015 um 10:58)

  • Bitte die Überschrift im ersten Beitrag anpassen auf: Script nur einmal ausführen
    (die Shell ist die Konsole, also nicht das was hier zutrifft)

    Lösung:

    Dein PHP Script übergibt an ein Bash oder Python Script ein Parameter wie zum Beispiel "klingel". Das Shellscript (bash / python) erstellt dann temporär eine lock Datei und spielt dann die jeweilige Datei ab und danach löscht es die lock Datei wieder. Führt man das Script wärend des Playbacks erneut aus muss eine Überprüfung ob das lockfile existiert eine erneute Ausführung verhindern.

    Beispiel:

    Anschließend solltest du noch einstellen das für /tmp/ ein tmpfs erzeugt wird (das sollte man generell machen), damit die SD nicht mit unnötigen Schreibvorgängen belastet wird. Dazu änderst du einfach in der Datei /etc/default/tmpfs die Einstellung RAMTMP=no auf RAMTMP=yes (und # entfernen) und rebootest.

    Ggf. ist /run/lock/ bereits als tmpfs gemountet, dann könnte Lockfile auch dort liegen...

  • Es waere viel einfacher wenn du hier deinen Python Code posten wuerdest.
    Du muesstest nach jedem abspielen eines Liedes nur den PI warten lassen bis er das naechste Lied spielt.
    time.sleep(t)
    das t steht fuer die Anzahl der Sekunden.

    A: Was ist dein dunkelstes Geheimnis?
    B: Das kann ich dir nicht sagen.
    A: sudo was ist dein dunkelstes Geheimnis?

  • Jupp gibt es mehrere Möglichkeiten.

    1. mit "ps" und "grep" checken ob der Prozess schon läuft

    Code
    ps -eaf | grep NAMEVONSKRIPTODERMP3DATEI
    if [ $? -ne 0 ]
    then
    SKRIPTSTARTEN
    fi

    2. Das Skript oder php einen kleine FLAG setzen lassen und nach beenden des Skriptes das FLAG wieder löschen und dann das SKript nur ausführen lassen, wenn das FLAG nicht gesetzt ist

    Nur so als 2 von 10 Möglichkeiten ;)

    --
    man ist das System-Anzeigeprogramm für die Handbuchseiten von Linux.


  • Du muesstest nach jedem abspielen eines Liedes nur den PI warten lassen bis er das naechste Lied spielt.
    time.sleep(t)
    das t steht fuer die Anzahl der Sekunden.

    Dann müsste man jedes mal wissen wie lang der Track bzw die Wiedergabe ist - ansonsten würde er pauschal 30 Sekunden warten müssen, was in manchen Fällen vielleicht nicht mals reichen könnte... Fände ich persönlich nicht so prickelnd.


    1. mit "ps" und "grep" checken ob der Prozess schon läuft

    Code
    ps -eaf | grep NAMEVONSKRIPTODERMP3DATEI
    if [ $? -ne 0 ]
    then
    SKRIPTSTARTEN
    fi

    2. Das Skript oder php einen kleine FLAG setzen lassen und nach beenden des Skriptes das FLAG wieder löschen und dann das SKript nur ausführen lassen, wenn das FLAG nicht gesetzt ist

    Dann bräuchte er 2 Scriptdateien? :-/
    "ps ax" würde btw reichen und "[ $(ps ax|grep playback.sh) == "" ] && playbach.sh" auch ;)

    Und was für ein FLAG meinst du? Wenn ich das richtig verstehe müsste das Script permanent laufen damit dein FLAG verwendet werden kann. Irgendwie glaub ich aber dass das nicht der Fall sein wird, und auch schwerer umzusetzen wäre falls doch...


    Eine weitere Möglichkeit wäre, die abzuspielenden Dateien in eine Playlist einzufügen und den Player einfach nur die Playlist abspielen zu lassen..

  • Danke ersteinmal für die Antworten.
    Also mein PHP Skript sieht so aus.

    Und ein Shellskript sieht so aus.

    Code
    echo "27" > /sys/class/gpio/export
    echo "out" > /sys/class/gpio/gpio27/direction
    
    
    echo "1" > /sys/class/gpio/gpio27/value
    mpg321 /home/pi/Desktop/Ruf/Texte/Text1.mp3
    echo "0" > /sys/class/gpio/gpio27/value

    Bei dem Problem was ich aktuell habe, ist python garnicht beteiligt :)

    Das Problem was ich hier sehe, es wird ja nur geschaut ob eine gewisse Datei abgespielt wird, aber es soll ja garkeine abgespielt werden.
    Gibt es evtl eine möglichkeit zu überprüfen ob die Soundkarte genutzt wird ?


    Gruß

    Martin

    Einmal editiert, zuletzt von skull2505 (25. Juni 2015 um 11:05)

  • Zunächst mal brauchst du nicht etlich verschiedene Scripte, das kannst du - wie ich zeigte - alles über eine einzige Datei regeln.

    Und das Lockfile sorgt eben dafür dass ein erneutes abspielen, wärend bereits etwas abgespielt wird, nicht erneut ausgeführt werden kann da das Lockfile noch existiert.
    Du drückst also auf einen Knopf, ein Script wird ausgeführt und spielt eine Datei ab. Drückst du wärend des abspielens erneut auf einen Knopf passiert nichts da 'Lockfile' noch da ist. Erst wenn das abspielen beendet wurde wird Lockfile gelöscht und erst danach kann man erneut etwas abspielen.

    Also Dein Code etwas aufgeräumt und somit übersichtlicher:


    PS: Bitte sehe davon ab Beiträge vollständig zu quoten.

  • Danke, dass du dir soviel mühe für mich machst.
    Ich hab das jetzt mal probiert, leider funktioniert das nicht so recht.
    ich habe auch geschaut ob durch das kopieren Fehler rein gekommen sind,
    aber keine zu finden.
    Die Pfade habe ich auch alle nochmal nachgesehen. Die passen alle.
    Apache hat auch keine Erroreinträge.

  • Führ halt mal das bash Script manuell aus - somit kannste das Problem weiter eingrenzen und siehst ob es generell so funktionieren würde wie du es dir vorstellst....

    Code
    bash (/home/pi/Desktop/Ruf/skripte/play.sh Text1 &; /home/pi/Desktop/Ruf/skripte/play.sh Text2)
  • Dann scheinst du die Datei unter Windows erstellt zu haben und somit hat diese ein nicht-linux-kompatibles-Dateiformat. Windows nutzt andere Zeilenumbruch's Zeichen als es Linux tut.

    Also: Datei vollständig löschen rm /home/pi/Desktop/Ruf/skripte/play.sh anschließend nano /home/pi/Desktop/Ruf/skripte/play.sh auf der Konsole ausführen und copy&paste den Code direkt dort rein.

  • So jetzt arbeitet er das Skript ab, aber ich bekomme die Fehlermeldungen

    line 15 write error Device or resource busy

    und

    files[Text1]: no such file or directory

    Wobei der Pfad dahinter aber stimmt.

    das Relais was ich zum Schalten einer Lampe nehme, funktioniert allerdings.

    Einmal editiert, zuletzt von skull2505 (25. Juni 2015 um 14:23)

  • Hast du die Funktion vor dem Aufruf deklariert? Also erst muss dem Script die function bekannt sein bevor sie ausgeführt werden kann. In der Reihenfolge hatte ich das auch oben gepostet.


    Davon unabhängig ist mir gerade noch ein Fehler meinerseits aufgefallen, und zwar muss aus files[$1] folgendes werden: ${files[$1]}
    Und declare -A files nach ganz an den Anfang einfügen, bevor das Array für "files" festgelegt wird.

    Spoiler anzeigen


    PS: Da ich dein angepasstes/ergänztes Script nicht kenne kann ich mit "line" Meldungen wenig anfangen...

  • Aber er spielt, egal welches Parameter (Text1, Text2, Text3) ich eingebe immer
    Text 3 ab.

    Füg noch declare -A files ganz an den Anfang des Scripts ein, bevor das Array für "files" festgelegt wird. Siehe Spoiler in Beitrag#14

  • Ah Super, glatt übersehen.

    Also das Skript funktioniert jetzt schonmal. :bravo2:
    Aber ich kann die Texte nicht über die PHP Seite starten.
    Wie bekomme ich denn raus, wo hier die information verloren geht.

    Die Seite habe ich ja auch kopiert, macht das da evtl. auch probleme?

    Gruß

    Martin

    Einmal editiert, zuletzt von skull2505 (25. Juni 2015 um 14:55)

  • Hm dann scheint etwas im <form> schief zu gehen..

    Änder mal die <form Zeile in folgendes:

    Code
    <form action="" method="post">

    (also id oder name rauswerfen)

    Und dann änderst du für jede <button> Zeile name="play" und trägst für value den individuellen Wert der beim drücken des Buttons übermittelt werden soll ein, also z.B.:

    Code
    <button class="Button" type="submit" name="play" value="Text1">Text1</button>
    ...
    <button class="Button" type="submit" name="play" value="Text6">Text6</button>
    Spoiler anzeigen

    [code=php]<!DOCTYPE HTML >
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Test</title>
    <style type="text/css">
    body {
    background-color:#000000;
    color: white;
    }
    .style {
    text-align:center;
    font-size:0px;
    font-family:"Verdana";
    }
    .Button {
    type:image;
    src="button3.jpg";
    width:760px;
    height:220px;
    }
    </style>
    </head>
    <body>
    <b>

    <?php
    if (isset($_POST['play']) AND !empty($_POST['play'])) {
    exec('/bin/bash /home/pi/Desktop/Ruf/skripte/play.sh '.$_POST['play'].'', $output, $return_var);
    if (!empty($output)) { foreach($output AS $line) { echo $line."<br/>\n"; } }
    }
    ?>

    <nobr>

    <form action="" method="post">
    <div class="style">
    <br>
    <button class="Button" type="submit" name="play" value="Text1">Text1</button>
    </div>

    <div class="style">
    <br>
    <button class="Button" type="submit" name="play" value="Text2">Text2</button>
    </div>

    <div class="style">
    <br>
    <button class="Button" type="submit" name="play" value="Text3">Text3</button>
    </div>

    <div class="style">
    <br>
    <button class="Button" type="submit" name="play" value="Text4">Text4</button>
    </div>

    <div class="style">
    <br>
    <button class="Button" type="submit" name="play" value="Text5">Text5</button>
    </div>

    <div class="style">
    <br>
    <button class="Button" type="submit" name="play" value="Text6">Text6</button>
    </div>

    </form>
    </nobr>
    </b>
    </body>
    </html>
    [/php]

    Das ließe sich übrigens auch einfacher gestalten indem man zu Anfang ein Array für die Buttons definiert und dann eine einfache Schleife jeden Button automatisch erstellt.. Dann brauch man nicht so viel im Code rum schreiben.

    [code=php]
    <?php
    //------ Buttons... Format: $Button['value']='Button Text';

    $Button['Text1']='Beschriftung von Button1';
    $Button['Text2']='Beschriftung von Button2';
    $Button['Text3']='Beschriftung von Button3';
    $Button['Text4']='Beschriftung von Button4';
    $Button['Text5']='Beschriftung von Button5';
    $Button['Text6']='Beschriftung von Button6';
    ?>

    <!DOCTYPE HTML >
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Test</title>
    <style type="text/css">
    body {
    background-color:#000000;
    color: white;
    }
    .style {
    text-align:center;
    font-size:0px;
    font-family:"Verdana";
    }
    .Button {
    type:image;
    src="button3.jpg";
    width:760px;
    height:220px;
    }
    </style>
    </head>
    <body>
    <b>

    <?php
    if (isset($_POST['play']) AND !empty($_POST['play'])) {
    exec('/bin/bash /home/pi/Desktop/Ruf/skripte/play.sh '.$_POST['play'].'', $output, $return_var);
    if (!empty($output)) { foreach($output AS $line) { echo $line."<br/>\n"; } }
    }
    ?>

    <nobr>

    <form action="" method="post">
    <?php
    foreach($Button AS $Value => $Text) {
    echo ' <br/><div class="style">';
    echo ' <button class="Button" type="submit" name="play" value="'.$Value.'">'.$Text.'</button>';
    echo " </div>\n";
    }
    ?>
    </form>
    </nobr>
    </b>
    </body>
    </html>
    [/php]

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!