# Linux bash script ausführen



## Albatrox (14. Mrz 2016)

Hallo Leute,

ich versuche gerade zu erreichen, dass mein Java Code einen Linux bash script ausführt, klappt soweit auch ganz gut, allerdings funktioniert es gerade nicht.


```
String cmd [] = {"sudo", "download.sh"};
Runtime.getRuntime().exec(cmd);
```

So in dem bash script sind mehrere wget anweisungen mit folgendem muster, bsp:
 wget -P ~/meinPfad/ -N http://www.investing.com/equities/evotec-ag-technical

Zuerst habe ich es ohne String cmd gemacht und dann kam ein Berechtigungsfehler auf, dann habe ich es auf ein String array, wie oben geändert und jetzt läuft der Code durch, aber das bash script wird nicht aufgeführt?!

Vielen Dank schonmal für die Hilfe.


----------



## Bitfehler (14. Mrz 2016)

Wie sah denn der Berechtigungsfehler aus?

Ich habe selber noch kein Bash-Skript aus Java heraus gestartet, aber die übergebenen Argumente sehen nicht wirklich korrekt aus. Download.sh ist sicherlich der Name des zu startenden Skripts, aber was willst du mit sudo an der Stelle bezwecken?


----------



## Baldur (14. Mrz 2016)

Wenn du ein Programm mittels "sudo" startest, muss sich normalerweise der aktuelle Benutzer mit seinem Passwort authentifizieren. Wenn du das Skript mittels Runtime.exec startest wartet sudo auf die Passworteingabe, die aber fehlt.

Ich halte es allerdings generell für falsch, in deinem Programm irgendwo einen sudo-Aufruf zu verstecken. Theoretisch müsstest du ja hier dein Passwort per OutputStream an den Prozess senden. Das ist eigentlich keine gute Idee, und normalerweise sollte ein Programm ohne root-Rechte auskommen. Vor allem wenn du einfach nur irgendwelche Dateien runterladen willst.
Vielleicht ist irgendwo in deinem Skript ein falscher Pfad angegeben, so daß das Skript nicht wie gedacht auf dein Home-Verzeichnis zugreift, sondern irgendwo anders im Dateisystem?

Ansonsten beschreib mal deinen Berechtigungsfehler.. evtl hat dein Bashskript einfach kein x-bit gesetzt?
Das könntest du auch umgehehn wenn du das Skript auf diese Weise startest:

```
String cmd [] = {"bash", "download.sh"};
Runtime.getRuntime().exec(cmd);
```


----------



## Albatrox (14. Mrz 2016)

Hallo zusammen, danke für die schnellen Antworten,

also das Problem mit der Berechtigung kam bei folgendem Code:

```
Runtime.getRuntime().exec("/usr/bin/Download.sh");
```

Die Fehlerausgabe ist die folgende:


Exception in thread "main" java.io.IOException: Cannot run program "/usr/bin/Download.sh": error=13, Keine Berechtigung
  at java.lang.ProcessBuilder.start(ProcessBuilder.java:1047)
  at java.lang.Runtime.exec(Runtime.java:617)
  at java.lang.Runtime.exec(Runtime.java:450)
  at java.lang.Runtime.exec(Runtime.java:347)
  at Code.test2.main(test2.java:11)    -> ist die oben geschriebene Zeile

Habe gerade noch deine Variante, Baldur, getestet und das Programm läuft durch alle Schritte durch, aber es passiert nichts. Ween ich in eclipse das Terminal benutze und den gleichen Befehl dort eingebe werden die Daten heruntergeladen.


----------



## Bitfehler (14. Mrz 2016)

Wie sind denn die Berechtigung auf die Datei gesetzt?


----------



## Baldur (14. Mrz 2016)

Gibts denn einen bestimmten Grund dafür, daß dein Skript unter /usr/bin liegt? Vermutlich sind einfach keine Lese- bzw. Ausführungsrechte für normale Benutzer gesetzt. Die Berechtigungen siehst du mit "ls -la /usr/bin/download.sh" in der Konsole.
Am Besten wäre es, wenn dein Skript irgendwo im selben Verzeichnis wie dein Java-Programm liegt. Von da kannst du es dann auch einfach mittels "bash $skriptname" ausführen.

Generell sollte man unter Linux nichts als root machen, wo es nicht absolut notwendig ist.


----------



## Albatrox (14. Mrz 2016)

Also Eigentürmer war root, habe ich auf mich geändert, aber das ist eigentlich egal oder? 
Berechtigungen habe ich für alle auf rwx umgestellt, trotzdem werden die Daten nicht geladen.


----------



## Bitfehler (14. Mrz 2016)

Zeig doch mal die Ausgabe von ls -la Pfad/Skript
Und gib mal -x als Parameter mit


----------



## Albatrox (14. Mrz 2016)

ls -la /usr/bin/Download.sh ergab:
-rwxrwxrwx 1 ich ich 2654 Mär    5   20:28.....


----------



## Albatrox (14. Mrz 2016)

Also ich habe no ein anderes bash script, welches eine pushbullet notiz schickt und das funtioniert über oben geschriebenen Code, auch im gleichen Ordner...


----------



## Baldur (14. Mrz 2016)

Führst du das Skript immernoch per sudo aus oder mittlerweile nicht mehr? Hast du mal geprüft ob der Prozess noch irgendwelche Ausgaben schreibt? Was ist der Returncode von deinem Prozess?
Evtl kannst du nochnal prüfen, ob in deinem Skript alle Pfade korrekt sind.


----------



## Albatrox (14. Mrz 2016)

nein nicht mehr per sudo, kommt auch keine Fehlermeldung. Ich habe immer ein system.out.println nach jedem schritt und die werden alle ausgegeben. Was mir noch aufgefallen ist, wenn ich nach dem "bash" noch ein leerzeichen lasse also "bash " dann wird der catch block aktiviert. 
Dacht nur, wenn ich das Script ins Terminal eingeben würde, müsste ich auch n leer zwischen bash und /usr/bin... lassen.

Wie kann ich den returncode von dem Prozess ausgeben?


----------



## Baldur (14. Mrz 2016)

Auf der Konsole brauchst du das Leerzeichen, um den Befehl von den Parametern zu trennen. Im Javacode hast du ja schon alles getrennt als jeweils einzelnes Element in deinem String-Array. Wenn du da noch Leerzeichen hinzufügst würde er nach einem Programm namens "bash<leerzeichen>" suchen. Mir ist auch aufgefallen, du hast download.sh schon einmal mit großem D und einmal mit kleinem d geschrieben. Unter Linux ist das ein Unterschied, hier wird zwischen Groß- und Kleinschreibung unterschieden, und das Skript wird evtl nicht gefunden, wenn der Name falsch geschrieben ist.

Den Returncode bekommst du mit process.exitValue(). Der sollte 0 sein, wenn alles Ok ist, und ungleich 0 bei Fehlern.


----------



## Bitfehler (14. Mrz 2016)

Wenn du dein Programm auf der Konsole ausführst, dann schreibt doch mal in die (zweite) Zeile eines Skripts:  set -x
Das Aktiviert den Debug-Modus und die Ausgaben werden auf die Konsole geschrieben. Dann wirst du erkennen können, an welchen Befehl es klemmt.


----------



## Albatrox (14. Mrz 2016)

Hab den Fehler gefunden *Kopfgegenwandhau*

Also dadurch dass das Herunterladen einige Zeit braucht, der Programmcode aber direkt weitergeht, reicht die Zeit nicht aus um die Seiten herunterzuladen. Ich habe einen Thread.sleep eingebaut, jetzt hat das script die Zeit die es benötigt damit die Seiten heruntergeladen werden.

Trotzdem vielen Dank nochmal 
Gruß


----------



## Baldur (14. Mrz 2016)

Benutz lieber "process.waitFor()", das wartet bis der Prozess beendet wurde.


----------



## Albatrox (14. Mrz 2016)

alles klar, teste ich gleich mal, danke


----------

