Terminal Intent Commands

G

GSUS24

Neues Mitglied
0
Hi
ich versuche gerade eine Verbindung über ssh zu bekommen (HTC One V cynogenmod 10) um beim Host einige Einstellung zu ändern.

Über das Terminal funktioniert das Einwandfrei. Jetzt versuche ich mich daran, dass in eine App zu packen, dass mir das Terminal mit den entsprechenden Befehlen öffnet.

Über diesen Intent gelingt es mir leider nur den ersten Befehl zu übergeben.

Code:
Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setComponent(new ComponentName("jackpal.androidterm", "jackpal.androidterm.RemoteInterface"));
        intent.setAction("jackpal.androidterm.RUN_SCRIPT");
        
//        intent.putExtra("jackpal.androidterm.iInitialCommand", "ssh root@192.168.178.27");
        
        
        startActivity(intent);

Danach sollte die Passworteingabe und die Änderungen am Host folgen.

Leider brachte auch google keine Antwort darauf.

Hat jemand von euch eine Idee, eine Reihe von Kommandos/Eingaben zu übergeben?

Habt Dank :)
 
Die simpelste Lösung, einfach Absätze \n in den String zu setzen funktioniert bis zur Verbindung mit dem Host. Es dauert 1-2 sek bis die Verbindung hergestellt ist und die Passwortabfrage kommt. Bis dahin wird die Eingabe nicht mehr berücksichtigt.

Code:
intent.putExtra("jackpal.androidterm.iInitialCommand", 
                "su\n" +
                "ssh-keygen -R [ip]\n" +
                "ssh root@ip\n" +
                "passwd\n");

Nach dem Befehl "ssh root@ip" sollte eine kurze Pause eingelegt werden und das Passwort verzögert übergeben werden.
Hat einer ne Ahnung wie ich das umsetzen kann?

Oder einen Alternativ-Vorschlag?

Bin über jeden Ansatz dankbar:thumbsup: hab den ganzen Mittag damit verbracht:angry:
 
Willst Du, dass das Terminal sich öffnet und Du die Befehle vom Host an das Terminal übergibts?

Hat das Terminal einen eingebauten Telnet/ssh Deamon?

Ich verwende SSH-Droid, um per SSH an mein Telefon ranzukommen. (Aber vielleicht verstehe ich auch Dein Anliegen falsch)

Grüsse Uwe
 
Hi Uwe,

ich verwende auf meinem HTC One V Android Terminal Emulator um auf meinen Openwrt Router zuzugreifen und muss hin und wieder einige Einstellungen ändern. Über das Terminal funktioniert das alles problemlos.

Die ganzen Kommandos will ich jetzt der Reihe nach aus meiner App aus übergeben. Wie gesagt komm ich mit dem oberen Intent nur bis zur Passworteingabe.

Wenn du hierfür eine Idee hast, nur her damit :biggrin:
 
Ist im Terminal-Emulator schon ein ssh-client drin oder rufst Du den erst aus dem Terminal auf (z.b. durch eingabe des Befehls ssh)?

Wenn ssh ein explizit aufrufbares binary ist, würde ich vorschalgen, in der app folgendes zu machen:

Code:
Process p = Runtime.getRuntime().exec("ssh");
final InputStream is = p.getInputStream();
Thread reader = new Thread()
{
   public void run()
   {
       try
       {
            BufferedReader r = new BufferedReader(new InputStreamReader(is));
            String line = br.readLine();
            while (line!=null)
            {
                 Log.v("SSH",line);
                 line = br.readLine();
            }
        }
        catch (Exception e){}
    }
};
OutputStream os = p.getOutputStream();
os.write(("any command"+"\n").getBytes());
os.flush();

Damit kannst Du an ssh alles senden, was Du magst.

Grüsse Uwe

Der ursprüngliche Beitrag von 21:00 Uhr wurde um 21:43 Uhr ergänzt:

Du kannst natürlich auch su als binary aufrufen und dann die weiteren kommandos absetzen:

Code:
Process p = Runtime.getRuntime().exec("su");
final InputStream is = p.getInputStream();
Thread reader = new Thread()
{
   public void run()
   {
       try
       {
            BufferedReader r = new BufferedReader(new InputStreamReader(is));
            String line = br.readLine();
            while (line!=null)
            {
                 Log.v("SSH",line);
                 line = br.readLine();
            }
        }
        catch (Exception e){}
    }
};
//vorhin vergessen: reader Thread starten!
reader.start();
OutputStream os = p.getOutputStream();
os.write("ssh-keygen -R [ip]\n".getBytes());
os.flush();
os.write("ssh root@ip\n".getBytes());
os.flush();
os.write("passwd\n".getBytes());
os.flush();
...

//zum Beenden (von su):
os.write("exit\n".getBytes());
os.flush();

Grüsse Uwe
 
Hi Uwe,
dank dir für deine Mithilfe. Leider hat dies auch nicht geklappt.
Ich denke dass es das selbe Problem ist wie auch in meiner Lösung, dass alle Befehle nach dem Login-Befehl: "ssh root@192.168.178.27" verloren gehen.

Wie gesagt vergehen zwischen Login-Befehl und Passwortabfrage gute 2 sek.
Meine Idee ist nach dem Login auf einen entsprechenden Input zu warten, bevor das Passwort übergeben wird.
Wie und woher ich die Info herbekomme, weiß ich nicht.

Wenn dir auch nichts mehr dazu einfällt, muss ich das wohl auf Eis legen und mir bleibt nichts anderes übrig als meine Kommandos stupide einzutippten.
 
Das ist ganz einfach, Du bekommst doch den InputStream vom Prozess-Object, aus dem wird die Antwort des Prozesses gelesen.


Code:
Process p = Runtime.getRuntime().exec("su");
[COLOR="Red"]final Object blocker = new Object();[/COLOR]
final InputStream is = p.getInputStream();
Thread reader = new Thread()
{
   public void run()
   {
       try
       {
            BufferedReader r = new BufferedReader(new InputStreamReader(is));
            String line = br.readLine();
            while (line!=null)
            {
                 Log.v("SSH",line);
                 [COLOR="Red"]if (line.statrsWith("password required"))
                 {
                      blocker.notify();
                 }[/COLOR]
                 line = br.readLine();
            }
        }
        catch (Exception e){}
    }
};
//vorhin vergessen: reader Thread starten!
reader.start();
OutputStream os = p.getOutputStream();
os.write("ssh-keygen -R [ip]\n".getBytes());
os.flush();
os.write("ssh root@ip\n".getBytes());
os.flush();
[COLOR="Red"]try
{
    blocker.wait();
    os.write("passwd\n".getBytes());
    os.flush();
}
catch (interruptedException e)        
{
    //hier behandeln, dass das warten auf das Passwort unterbrochen wurde
}[/COLOR]
...

//zum Beenden (von su):
os.write("exit\n".getBytes());
os.flush();

Schau Dir mal die drei roten Passagen im Code an...

Grüsse Uwe

Der ursprüngliche Beitrag von 09:59 Uhr wurde um 10:02 Uhr ergänzt:

Genaugenommen muss das gleiche wie mit dem InputStream den man mit p.getInputStream() bekommt (das ist nähmlich der 'stdout' des Prozesses auch mit dem InputStream, den man mit p.getErrorStream() bekommt, gemacht werden (das ist der 'stderr' des Prozesses)

Grüsse Uwe
 
Hi

um den Code ohne Abstürze zum laufen zu bringen war noch dies hier nötig
Code:
synchronized(blocker) {
                    blocker.wait();
                    os.write("123\n".getBytes());
                    os.flush();
                }

Habe ich das richtig verstanden, dass blocker.wait() solange wartet bis blocker.notify() aufgerufen wird, mit dem Vergleich
Code:
if (line.startsWith("root@192.168.178.27's password:"))
                             {
                                  blocker.notify();
                             }

Irgendwo bleibt er im Code hängen, da wahrscheinlich der Vergleich des Strings nicht stimmt und blocker.notify() nie aufgerufen wird.

Ich versuche gerade mir den InputStream nach dem ssh-login anzeigen zulassen um den Vergleich zu ändern.

In der while lasse ich mir den line-String in eine Textview anzeigen.

Code:
while (line!=null)
                        {
                             Log.v("SSH",line);
//                             if (line.startsWith("root@192.168.178.27's password:"))
//                             {
//                                  blocker.notify();
//                             }
                             line = br.readLine();

                             tvLINE = v.findViewById(R.id.showline);
                             ((TextView)tvLINE).setText("Show" + line);
                        }

Nur wird mir nichts angezeigt. Es kommt mir so vor das line=null bleibt und so auch nichts angezeigt werden kann.
 
Zur Ausgabe:

Versuchs mal sorum, nach dem readLine ist die erste Zeile weg:
Code:
while (line!=null)
                        {
                             Log.v("SSH",line);
                            [COLOR="Red"] tvLINE = v.findViewById(R.id.showline);
                             ((TextView)tvLINE).setText("Show" + line);[/COLOR]
//                             if (line.startsWith("root@192.168.178.27's password:"))
//                             {
//                                  blocker.notify();
//                             }
                             line = br.readLine();

                        }

Zum es bleibt hängen:, das kommt vom synchronized:(Ich ziehe den grauen Teil meiner Aussage zurück, war Unsinn)

Wieso denkst du du müsstest um das Blocker ein synchronized setzen, so wird das Object gesperrt, und die notify() Methode kann nicht aufgerufen werden.(Ich ziehe den grauen Teil meiner Aussage zurück, war Unsinn)

In dem Code kommt auch kein zweiter Thread in die Bereich rein, den Du mit synchronized gesperren woltest.



Der ursprüngliche Beitrag von 17:24 Uhr wurde um 17:49 Uhr ergänzt:

Moment, ich habe über die Aussage mit dem synchroized nochmal nachgedacht, glaube doch nicht, dass synchronized(blocker) den zugriff eines fremden Threads auf die blocker.notify() sperrt.

Aber falls es einen zweiten Thread gibt, der durch

Code:
                    blocker.wait();
                    os.write("123\n".getBytes());
                    os.flush();

läuft (und nur in dem Fall würde ein sychronized Sinn machen), dann läuft da was ganz anders, als es in meinem Codebeispiel gezeigt werden soll.

Das ganze Beispiel darf nur von einem Thread durchlaufen werden!

Der zweite Thread (den ich in meinem Beispiel selbst erzeuge) für den Reader darf nur durch die Methode run laufen:

Code:
Thread reader = new Thread()
{
   public void run()
   {
       try
       {
            BufferedReader r = new BufferedReader(new InputStreamReader(is));
            String line = br.readLine();
            while (line!=null)
            {
                 Log.v("SSH",line);
                 if (line.statrsWith("password required"))
                 {
                      blocker.notify();
                 }
                 line = br.readLine();
            }
        }
        catch (Exception e){}
    }
};


Grüsse Uwe
 
Zuletzt bearbeitet von einem Moderator:
Sorry das ich das Thema immer noch am Leben halte. Ich hab jetzt schon so viel Zeit investiert, dann möchte ich auch ein Ergebnis :flapper:
Aber ohne eure Hilfe, speziell Uwes, sehe ich kein Land.

Jetzt versuche ich stdout zu lesen
Mit diesem Code bekomme ich auch das selbe Ergebnis wie auch per Eingabe in meinem Terminal.

Code:
Process p;
        try {
            p = Runtime.getRuntime().exec("/system/bin/ls /sdcard");
            final InputStream is = p.getInputStream();
            Thread reader = new Thread()
            {
               public void run()
               {                   
                   try
                   {                       
                        BufferedReader br = new BufferedReader(new InputStreamReader(is));
                        String line = br.readLine();
                                            
                        tvLINE = v.findViewById(R.id.showline);
                           ((TextView)tvLINE).setText("Show " + line);
                                            
                        while (line!=null)
                        {
                             Log.v("SSH",line);
                             line = br.readLine();
                        }
                                            
                    }
                    catch (Exception e){}
                }
            };
            
            reader.start();
            
            [COLOR=Red]p.waitFor();[/COLOR]
            [COLOR=Red]} catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();[/COLOR]
            
        
        }     catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
            }

Ist das selbe wie von Uwe vorgeschlagen, lediglich der rot markierte Teil hat gefehlt.

Rufe ich statt "/system/bin/ls /sdcard"den Befehl "ssh root@ipaddr" auf, liefert mir stdout = null !!!???

Laut Terminal erwarte ich:
"The authenticity of host ... can´t be established ...Are you sure you want to connect (yes/no)"
Darum habe ich vorerst versucht über SuperUser und den Host als bekannt anzugeben, diese Meldung zu umgehen und sofort zur Passworteingabe zu gelangen. Aber der Versuch eine Verbindung über ssh zu bekommen scheitert schon.

Und jetzt bin ich völlig ahnungslos, ob meine Idee überhaupt bzw. für mich umzusetzen ist.
 
Nochmal die Frage:

Hast Du es GENAU so probliert?

Als Prozess 'su' starten:

u.k-f schrieb:
...
Code:
Process p = Runtime.getRuntime().exec("su");
[COLOR="Red"]final Object blocker = new Object();[/COLOR]
final InputStream is = p.getInputStream();
Thread reader = new Thread()
{
   public void run()
   {
       try
       {
            BufferedReader r = new BufferedReader(new InputStreamReader(is));
            String line = br.readLine();
            while (line!=null)
            {
                 Log.v("SSH",line);
                 [COLOR="Red"]if (line.statrsWith("password required"))
                 {
                      blocker.notify();
                 }[/COLOR]
                 line = br.readLine();
            }
        }
        catch (Exception e){}
    }
};
//vorhin vergessen: reader Thread starten!
reader.start();
OutputStream os = p.getOutputStream();
os.write("ssh-keygen -R [ip]\n".getBytes());
os.flush();
os.write("ssh root@ip\n".getBytes());
os.flush();
[COLOR="Red"]try
{
    blocker.wait();
    os.write("passwd\n".getBytes());
    os.flush();
}
catch (interruptedException e)        
{
    //hier behandeln, dass das warten auf das Passwort unterbrochen wurde
}[/COLOR]
...

//zum Beenden (von su):
os.write("exit\n".getBytes());
os.flush();

Grüsse Uwe
 
  • Danke
Reaktionen: GSUS24
Möglicherweise stelle ich mich auch zu doof an :confused:

Also dein Code wird in einem ActionBarTab(Fragment) aufgerufen,
den ich noch mich try/catch versehen musste

Code:
try{
      //Dein Codeschnipsel
     
     } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

Ein Klick auf den Tab und die App wird beendet.

LogCat liefert mir das hier:

Code:
 04-10 13:12:38.414: E/AndroidRuntime(24063): FATAL EXCEPTION: main
  04-10 13:12:38.414: E/AndroidRuntime(24063): java.lang.IllegalMonitorStateException: object not locked by thread before wait()
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at java.lang.Object.wait(Native Method)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at java.lang.Object.wait(Object.java:364)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at com.camera.simplemjpeg.OutputStream_Fragment.processUWE2(OutputStream_Fragment.java:260)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at com.camera.simplemjpeg.OutputStream_Fragment.onCreateView(OutputStream_Fragment.java:37)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:829)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at android.app.BackStackRecord.run(BackStackRecord.java:635)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1397)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at android.app.FragmentManagerImpl$1.run(FragmentManager.java:426)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at android.os.Handler.handleCallback(Handler.java:615)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at android.os.Handler.dispatchMessage(Handler.java:92)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at android.os.Looper.loop(Looper.java:137)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at android.app.ActivityThread.main(ActivityThread.java:4965)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at java.lang.reflect.Method.invokeNative(Native Method)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at java.lang.reflect.Method.invoke(Method.java:511)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:558)
  04-10 13:12:38.414: E/AndroidRuntime(24063):                at dalvik.system.NativeStart.main(Native Method)
  04-10 13:12:43.248: D/AndroidRuntime(24303): Calling main entry com.android.commands.am.Am

Mir fehlt einfach die Erfahrung, Fehler daraus zu lesen.
Auf der Suche nach einer Lösung, fand ich
synchronized()
mit dem Zusatz wird die App nicht mehr beendet, aber tut auch nicht was sie soll.

Vielleicht liegts auch am Fragment, was ich selber nicht glaube.
Da mit dem Code aus vorherigem Post, mir eine Antwort auf den Befehl angezeigt wird.
 
Das ist eine interessante Fehler-Meldung.

Dann lass uns OHNE den wait/notify arbeiten:

Möglicherweise war das Problem auch, dass readLine() geblockt hat, da nach 'password required' keine Zeilen-umbruch geschickt wurde.

Dann kann man nicht mit readLine arbeiten, sondern muss es so machen:

Zunächst eine kleine Helfer-Class um auf wait/notify zu verzichten:

Code:
public class WaitHelper
{
    public boolean i_wait = true;
}

Und hier nutzen wir das:

Code:
Process p = Runtime.getRuntime().exec("su");
final WaitHelper wh = new WaitHelper()
final InputStream is = p.getInputStream();
Thread reader = new Thread()
{
   public void run()
   {
       try
       {
            StringBuffer s = new StringBuffer();
            int r = is.read();
            while (r!=-1)
            {
                 if (r=='\n' || r=='\r')
                 {
                     Log.v("SSH","Read comlete line "+s.toString());
                     //alte Zeile löschen, nächste zu lesen anfangen...
                     s.setLength(0);
                 }
                 else
                 {
                     s.append((char)r);
                     String l = s.toString();
                     Log.v("SSH","Read partial line "+l);
                     if (l.startsWith("password required"))
                     {
                         wh.i_wait=false;
                     }
                 }
                 r = is.read();
            }
        }
        catch (Exception e){}
    }
};
reader.start();
OutputStream os = p.getOutputStream();
os.write("ssh-keygen -R [ip]\n".getBytes());
os.flush();
os.write("ssh root@ip\n".getBytes());
os.flush();
while (wh.wait())
{
    try
    {
        Thread.sleep(100);
    }
    catch (InterruptedException e)        
    {
    }
}
os.write("passwd\n".getBytes());
os.flush();
...

//zum Beenden (von su):
os.write("exit\n".getBytes());
os.flush();

Grüsse Uwe
 
  • Danke
Reaktionen: GSUS24
Danke für deinen Einsatz :thumbsup: Du hast mir jetzt mehrere Alternativen gezeigt, mit denen man arbeiten kann. Nur leider funktioniert das in meinem speziellen Fall nicht.

Die Antwort auf den Befehl "ssh root@192.168.178.27" lt. Terminal:
"root@192.168.178.27's password:"

Muss der String in der if(l.startsWith("...")) 1zu1 übereinstimmen?
Oder reicht hier ein "root@192.168.178.27"?
Das sit eine mögliche Fehlerquelle, da ohne Übereinstimmung das wh.i_wait-flag nicht zurücksetzt wird und ewig in der while(wh.i_wait) hängen bleibt. Es sieht mir ganz danach aus.


Ich bin im debuggen nicht wirklich fit. Dort sollte ich doch mit paar breakpoints nachverfolgen können und die Antworten auf meine Befehle sehen!?
Mach das grad ziemlich umständlich mit ein/auskommentieren, bisher hat das gereicht :) Aber das soll mal mein Problem bleiben:cursing:


Was mich skeptisch macht, wenn ich mir zwischen drin eine Textview ausgeben lasse und alles auf den ersten Befehl "ssh root@192.168.178.27" reduziere. Dann ist die Antwort darauf null
Mit dem Befehle "/system/bin/ls /sdcard" wie erwartet /sdcard

Wie gesagt, sollte ohne SuperUser "su", etwas wie "Host can't be established" kommen

Ich hab irgendwo gelesen, dass z.B. CustomRoms unterschiedliche/eigene shell Befehle besitzen. Ist es möglich dass darum "ssh" bei mir keine Antwort liefert?

Je mehr ich mich damit befasse, umso mehr Fragen kommen auf:confused:

Aber jetzt will ich es umso mehr wissen, ich schau mich auch bei Stackoverflow um, möglicherweise findet sich hat dort was für mein Problem.
 
GSUS24 schrieb:
...Muss der String in der if(l.startsWith("...")) 1zu1 übereinstimmen?
Oder reicht hier ein "root@192.168.178.27"?
Das sit eine mögliche Fehlerquelle, da ohne Übereinstimmung das wh.i_wait-flag nicht zurücksetzt wird und ewig in der while(wh.i_wait) hängen bleibt. Es sieht mir ganz danach aus....

l.startsWith("...") prüft, ob l mit genau den Zeichen in "..." anfängt.

Code:
String l = "Hugo und Kurt";
System.out.println(l.startsWith("Hugo "));
System.out.println(l.startsWith("hugo "));
System.out.println(l.startsWith("Hugo Und"));

liefert

Code:
true
false
false

was aber deutlich weinger anspruchsvoller Test ist:

Code:
String l = "Hugo und Kurt";
System.out.println(l.toUpperCase().indexOf("HUGO ")>-1);
System.out.println(l.toUpperCase().indexOf("HUGO UN")>-1);
System.out.println(l.toUpperCase().indexOf(" UND K")>-1);

würde:
Code:
true
true
true
liefern.

Grüsse Uwe
 
  • Danke
Reaktionen: GSUS24

Ähnliche Themen

4
Antworten
8
Aufrufe
1.423
469110
4
E
Antworten
1
Aufrufe
831
enrem
E
znieh99
  • znieh99
2
Antworten
24
Aufrufe
2.469
swa00
swa00
Zurück
Oben Unten