Shellskript aus einem C++ Programm starten
-
Tja, erstmal sagst du mir, welche Befehle dafür in Telnet erforderlich sind. Ich muss schließlich wissen, was ich senden muss. Protokolliere einfach die gesamte Telnet-Sitzung einschließlich des Startens des Skriptes.
P.S.: Wo erfolgt denn die Ausgabe des Skriptes? Läuft das dann auch in der Telnet Umgebung (in der Konsole) oder auf deinem Compi?
-
Ich gehe wie folgt vor:
Start->Ausführen->Telnet
Im Fenster das aufgeht ->
open user/pw@unix (Unix ist der Rechner auf dem die Skripte liegen)
cd Skripte (der Ordner auf dem Unix Rechner)
dvl_bk.sh (das zustartende Skript)P.S.: Das Skript läuft selbstständig. Nach dem letzten Befehl (dvl_bk.sh) kann die Verbindung getrennt werden.
-
Du könntest natürlich auch einfach die Telnet-Komponente aus dem Indy-Paket benutzen ...
-
Gibt es da nicht irgendeine einfache Möglichkeit mit dem Borland Builder?
Die Idee vom WebFritzi wäre mir am liebsten, aber ich brauchte ein Beispiel, da ich mit dieser Komponente noch nie gearbeitet hab.
-
Bountblasher schrieb:
Start->Ausführen->Telnet
Das kenne ich noch garnicht. Ich mache das immer in der Eingabeaufforderung: telnet smtp.web.de 25[Return]. Wieder was neues gelernt.
Bountblasher schrieb:
Im Fenster das aufgeht ->
open user/pw@unix (Unix ist der Rechner auf dem die Skripte liegen)Kommt da denn dann auch ein Trennstrich (/) zwischen deinen Usernamen und das Passwort (z.B. "open WebFritzi/MyPass@unix")? Beantworte mir nur noch diese Frage. Dann kann ich dein Problem bearbeiten.
Bountblasher schrieb:
P.S.: Das Skript läuft selbstständig. Nach dem letzten Befehl (dvl_bk.sh) kann die Verbindung getrennt werden.
Kann die Verbindung sofort getrennt werden durch ein "quit"?
P.S.: Ach ja, wichtig: der Hostname des Computers, mit dem du dich verbinden willst, ist "unix", ja? Stimmt das so? Das Problem ist: mit was soll verbunden werden? Mit "unix" oder mit "user/pw@unix"? Was heißt dieses @-Zeichen in diesem Zusammenhang? Der Hostname ist "unix", OK, aber welchen Hostnamen muss ich in meine Connect-Funktion reinschreiben? "unix" oder "user/pw@unix"?
-
Bountblasher schrieb:
Gibt es da nicht irgendeine einfache Möglichkeit mit dem Borland Builder?
Einfacher als mit einer Komponente geht's wohl kaum. Und unter den Beispielen gibt es auch ein Telnetclient-Projekt.
Aber ich sehe schon, du bist auf eine Fix-Fertig-Lösung aus. Denn sonst könntest du WebFritzis Vorschlag, ohne irgendwelche Details zu kennen, ja wohl kaum von vonherein bevorzugen.
-
Ja UNIX ist der PC mit dem ich mich verbinden will.
Es würde reichen, wenn in der Connect-Funktion UNIX steht.
Das @ zeigt nur an, das jetzt der PC kommt mit dem man sich verbinden will genau so wie der / den Benutzernamen vom Passwort trennt.PC: UNIX
Benutzer: user
Passwort: pw@Jansen Nein ich bin nicht nach auf eine Fix und fertigen Lösung aus, aber ich würde mir das Beispiel von WebFritzi gerne mal anschauen. Bin auch nebenbei beim ausprobieren deines Tipps.
Danke schon mal im voraus für eure Hilfe.
-
Bountblasher schrieb:
Das @ zeigt nur an, das jetzt der PC kommt mit dem man sich verbinden will genau so wie der / den Benutzernamen vom Passwort trennt.
PC: UNIX
Benutzer: user
Passwort: pwKönntest du dich bitte klarer ausdrücken? Du gehst davon aus, dass ich mich mit Telnet auskenne - tu ich aber nicht. Wenn ich nun nur "UNIX" in meine Connect-Funktion schreibe, wie soll ich dann den Benutzer und den Pass angeben??? Sagen wir, du schreibst in telnet nur "open UNIX". Musst du danach dann den Benutzernamen und das Passwort angeben? Wenn ja, wie? Nacheinander? Bitte um ein fiktives Protokoll.
-
Ich gebe in der Eingabeaufforderung folgendes ein:
Telnet UNIX [Enter]
dann kommt die Ausgabe:
HP-UX UNIX B.11.11 U 9000/800 (tm)login: user [Enter]
Password: pw [Enter]login und Password ist eine Ausgabe vom System, ich gebe nur den
Benutzer "user" und das Passwort "pw" ein.
-
Bis Fritzi so in die Puschen kommt (;)) zeige ich mal eine Indy-Variante.
//--------------------------------------------------------------------------- bool logged_in = false; String strLogin = "jansen"; String strPass = "pass"; String strCommand = "touch test.dat;ls -l test.dat;rm test.dat"; String strResponse = "-rw-r--r-- 1 jansen users"; String strText = ""; void __fastcall TForm1::TN1DataAvailable(TIdTelnet *Sender, const AnsiString Buffer) { if (Buffer != "") { if (!logged_in) { // Loginprompt erreicht if (UpperCase(Buffer).Pos("LOGIN: ") == Buffer.Length() - 6) strText = strLogin; // Passwortprompt erreicht else if (UpperCase(Buffer).Pos("PASSWORD: ") == Buffer.Length() - 9) strText = strPass; // Eingabeprompt erreicht, Kommando abschicken else if (UpperCase(Buffer).Pos(UpperCase("jansen@suse82:~> ")) > 0) { logged_in = true; strText = strCommand; } } // Ausgabe enthält erwartetes Resultat des Kommandos, Verbindung beenden else if (UpperCase(Buffer).Pos(UpperCase(strResponse)) > 0) strText = "exit &"; if (strText != "") { // das eigentliche Versenden for (int i = 1; i <= strText.Length(); i++) TN1->SendCh(strText[i]); TN1->SendCh(VK_RETURN); strText = ""; } // Kontrollausgabe Memo1->Lines->Add(Buffer); } } //---------------------------------------------------------------------------
TN1 ist die Indy-Komponente, Connect und Disconnect erfolgen im Formkonstruktor/-destruktor.
-
Wie bau ich die Verbindung auf? So was wie Active oder open hab ich nicht gefunden.
-
Jansen schrieb:
... Connect und Disconnect ...
Wie könnten entsprechende Methoden wohl heissen?
-
Hab ich dann auch gemerkt
*schäm*
Noch mal eine Frage zu deinem Beispiel.
Ich hab alles so gemacht wie du, funktioniert auch wunderbar.
Mein Unix sieht ein bisschen anders aus als deins, wie kann ich bei mir prüfen in was für einem Verzeichnis ich mich befinde?user@UNIX [/user/dwhst/]
$Bei dem $ Zeichen kann ich meinen Code eingeben. Hab dein Skript schon so abgeändert, das ich in das () Verzeichnis wechseln kann.
Wie kann ich aber abfragen ob ich wirklich in diesem Verzeichnis bin?
-
Du musst halt immer den letzten Output auswerten (die Buffer-Variable). Da steht das drin, was du auch nach einer Eingabe an der Konsole sehen würdest.
-
Bountblasher schrieb:
Ich gebe in der Eingabeaufforderung folgendes ein:
Telnet UNIX [Enter]
dann kommt die Ausgabe:
HP-UX UNIX B.11.11 U 9000/800 (tm)login: user [Enter]
Password: pw [Enter]login und Password ist eine Ausgabe vom System, ich gebe nur den
Benutzer "user" und das Passwort "pw" ein.Wenn du das gleich so gesagt hättest, dann hätte ich dir sofort diesen Code geben können:
#include <windows.h> #include <winsock2.h> //--------------------------------------------------------------------------- VOID ErrorMsg(HWND hwnd, LPCTSTR lpszErr) { MessageBox(hwnd, TEXT(lpszErr), TEXT("ERROR"), MB_OK | MB_ICONERROR); } //--------------------------------------------------------------------------- VOID ShowLastSockError(HWND hwnd) { LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)&lpMsgBuf, 0, NULL); MessageBox(hwnd, (LPCTSTR)lpMsgBuf, TEXT("ERROR"), MB_OK | MB_ICONERROR); LocalFree(lpMsgBuf); } //--------------------------------------------------------------------------- BOOL StartWinsock2() { WSADATA wsa; int retVal = WSAStartup(MAKEWORD(2,0), &wsa); if(retVal == 0) return TRUE; else { switch(retVal) { case WSASYSNOTREADY: ErrorMsg(NULL, "The underlying network subsystem is not ready for network communication"); case WSAVERNOTSUPPORTED: ErrorMsg(NULL, "The version of Windows Sockets support requested (2.0) is not provided by this particular Windows Sockets implementation."); case WSAEINPROGRESS: ErrorMsg(NULL, "A blocking Windows Sockets 1.1 operation is in progress"); case WSAEPROCLIM: ErrorMsg(NULL, "Limit on the number of tasks supported by the Windows Sockets implementation has been reached"); case WSAEFAULT: ErrorMsg(NULL, "Implementation Error"); } return FALSE; } } //--------------------------------------------------------------------------- BOOL EndWinsock2() { if( WSACleanup() == 0 ) return TRUE; else { ShowLastSockError(NULL); return FALSE; } } //--------------------------------------------------------------------------- SOCKET SetupSocket() { SOCKET retVal = socket(AF_INET, SOCK_STREAM, 0); if(retVal != INVALID_SOCKET) return retVal; else { ShowLastSockError(NULL); return NULL; } } //--------------------------------------------------------------------------- BOOL CloseSocket(SOCKET s) { if( closesocket(s) == 0 ) return TRUE; else { ShowLastSockError(NULL); return FALSE; } } //--------------------------------------------------------------------------- ULONG GetIPFromString(LPTSTR hostnameOrIp) { ULONG retVal; HOSTENT* he; // Is there an IP in hostnameOrIp? retVal = inet_addr(hostnameOrIp); if(retVal == INADDR_NONE) // NO { he = gethostbyname(hostnameOrIp); if(he == NULL) // An error occured { ShowLastSockError(NULL); return 0; } else // everything's fine // Copy the first 4 bytes from he->h_addr_list to ip CopyMemory((PVOID)&retVal, he->h_addr_list[0], 4*sizeof(BYTE)); } return retVal; } //--------------------------------------------------------------------------- BOOL Connect(SOCKET s, USHORT port, LPCTSTR lpszCompName) { SOCKADDR_IN addr; int rc; ZeroMemory((PVOID)&addr, sizeof(SOCKADDR_IN)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = GetIPFromString((LPTSTR)lpszCompName); rc = connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR)); if(rc == 0) return TRUE; else { ShowLastSockError(NULL); return FALSE; } } //--------------------------------------------------------------------------- BOOL Send(SOCKET s, char* buf, int len) { int bytes_sent; bytes_sent = send(s, buf, len, 0); if(bytes_sent != SOCKET_ERROR) return TRUE; else { ShowLastSockError(NULL); return FALSE; } } //--------------------------------------------------------------------------- BOOL Receive(SOCKET s, char* buf, int len) { int bytes_received; bytes_received = recv(s, buf, len, 0); if(bytes_received != SOCKET_ERROR) return TRUE; else { ShowLastSockError(NULL); return FALSE; } } //--------------------------------------------------------------------------- #pragma argsused WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SOCKET s; char buf[4096]; if( !StartWinsock2() ) return 0; s = SetupSocket(); if(s == NULL) { EndWinsock2(); return 0; } if( !Connect(s, 23, "UNIX") ) { CloseSocket(s); EndWinsock2(); return 0; } Receive(s, buf, 4096); Send(s, "Username\r\n", 10); Receive(s, buf, 4096); Send(s, "Pass\r\n", 6); Receive(s, buf, 4096); Send(s, "cd Skripte\r\n", 12); Receive(s, buf, 4096); Send(s, "dvl_bk.sh\r\n", 11); Receive(s, buf, 4096); Send(s, "quit\r\n", 6); Receive(s, buf, 4096); if( !CloseSocket(s) ) { EndWinsock2(); return 0; } if( !EndWinsock2() ) return 0; return 1; } //---------------------------------------------------------------------------
Der Code ist nicht getestet, da ich keinen Server kenne, bei dem man Benutzername und Pass eingeben muss. Ich hoffe, du kannst auch damit ein wenig was anfangen.
-
äh ja, schön, Fritzi... nur sind wir hier im VCL Forum und haben glücklicherweise den TClientSocket, welcher uns n Haufen von dem WinAPI-Gewusel da abnimmt und die Verwendung von Sockets erheblich erleichtert (o;
-junix
-
junix schrieb:
äh ja, schön, Fritzi... nur sind wir hier im VCL Forum und haben glücklicherweise den TClientSocket, welcher uns n Haufen von dem WinAPI-Gewusel da abnimmt und die Verwendung von Sockets erheblich erleichtert (o;
Ja schön, junix. Aber du hast wohl mitbekommen, dass Bountblasher mich darum gebeten hatte, ihm etwas Code zu geben. Wenn nicht, dann lies den Thread nochmal durch. Tut dir gut! Ich habe somit lediglich mein Versprechen eingelöst. Ganz davon abgesehen arbeitet deine tolle Klasse sicher auch mit genau den Funktionen, mit denen ich arbeite. Warum sollte Bountblasher nicht wissen, was wirklich dahinter steckt. Und nochmal außerdem: ich habe diese Klasse nicht, denn ich hab den BCB3.
-
WebFritzi schrieb:
Aber du hast wohl mitbekommen, dass Bountblasher mich darum gebeten hatte, ihm etwas Code zu geben. Wenn nicht, dann lies den Thread nochmal durch. Tut dir gut!
danke, brauche keine Leseübungen und ich wüsste nicht wieso sonst mir das gut tun sollte. (:
WebFritzi schrieb:
Ganz davon abgesehen arbeitet deine tolle Klasse sicher auch mit genau den Funktionen, mit denen ich arbeite.
Ich glaube du solltest mein Posting nochmals lesen statt gleich rot zu sehen, nur weil man eine kritische Äusserung macht... täte dir wohl ganz gut.... Ich sagte ausdrücklich dass sie komfortabler im Handling sei. Zu deinem Funktionsset bräuchte man noch einen Thread der die IO-Aufgaben übernimmt um sie effizient einsetzen zu können.
WebFritzi schrieb:
Warum sollte Bountblasher nicht wissen, was wirklich dahinter steckt.
Wer sagt denn sowas? Es geht nur darum, dass in der ersten Phase die Erfolgschancen höher und das Verständnis leichter ist als wenn man gleich aus dem Vollen schöpft... vor Allem dann, wenn man sich auf absolutem neuland bewegt...
WebFritzi schrieb:
Und nochmal außerdem: ich habe diese Klasse nicht, denn ich hab den BCB3.
Tja... Für leute mit dem BCB < 5 (oder 4?) haben wir ja auch noch die Indy-Library die dir auch nicht unbekannt sein dürfte....
Also spiel hier nicht gleich den beleidigten Webfritzen. War ja kein persönlicher Angriff sondern nur ein Hinweis am Rande...
-junix
-
junix schrieb:
Für leute mit dem BCB < 5 (oder 4?) haben wir ja auch noch die Indy-Library die dir auch nicht unbekannt sein dürfte....
Ne, isse nich. Aber die ist nicht für den BCB3 gedacht, soweit ich mich erinnern kann.
junix schrieb:
Also spiel hier nicht gleich den beleidigten Webfritzen. War ja kein persönlicher Angriff sondern nur ein Hinweis am Rande...
Auch wenn es nicht wie ein "Hinweis am Rande" daherkam... Ich bin nicht beleidigt. Ich habe lediglich meinen Post gerechtfertigt.
Zum Thread: Wieso? Meinst du nicht, einer reicht? Ich hatte eben an ein Programm für ihn gedacht, dessen Symbol er nur anzuklicken braucht, und schon ist das Skript gestartet. Da braucht's kein Input.
-
WebFritzi schrieb:
junix schrieb:
Für leute mit dem BCB < 5 (oder 4?) haben wir ja auch noch die Indy-Library die dir auch nicht unbekannt sein dürfte....
Ne, isse nich. Aber die ist nicht für den BCB3 gedacht, soweit ich mich erinnern kann.
Äh die älteren Versionen... (damals hiess sie glaube ich WinShoes...) würden da helfen...
WebFritzi schrieb:
Zum Thread: Wieso? Meinst du nicht, einer reicht? Ich hatte eben an ein Programm für ihn gedacht, dessen Symbol er nur anzuklicken braucht, und schon ist das Skript gestartet. Da braucht's kein Input.
Jo, dann gehts... trotzdem wäre ein Thread eleganter um das UI zu entkoppeln...
-junix