In Cygwin gibt es keinen Sudo-Befehl

40

Weil es keine gibt sudo befehl in Cygwin , Skripte, die ich ausführen möchte, schlagen fehl

./install.sh: line N: sudo: command not found

Was ist die Standardmethode, um das zu umgehen? Bearbeiten der zu entfernenden Skripte sudo? Einige bekommen sudo -ähnliches Tool für Windows?

Jason Sundram
quelle
@dotancohen, ich hoffe, ich habe den richtigen ausgewählt.
Jason Sundram
Sieht nach einer guten Lösung für mich aus! Cygwin-Support ist in den letzten fünf Jahren sicherlich besser geworden!
dotancohen
@Benj, ich frage mich, warum diese Frage auch hier nicht migriert wurde.
Jason Sundram
@JasonSundram in der Tat. Lassen Sie mich wissen, wenn die Antwort verschoben wird, dann aktualisiere ich den Link.
Benj

Antworten:

8

Ich habe das geschrieben (eher simpel) TOUACExt zum SUDO für CygWin , eine Pre-Beta-Shell-Skript-Automatisierung, die sich dem nähert Verhalten der klassischen sudo für Linux:

  • Öffnet und schließt automatisch sudoserver.py bei Bedarf.
  • Anfragen UAC Eingabeaufforderung.

Installation erfordert das Kopieren der vier .sh Skripte zu einem Pfadverzeichnis, erstellen einen Alias ​​und nur ein paar weitere Schritte, die im Thread beschrieben werden.

Die Ergebnisse : Sie geben eine einzelne ein sudo YourCommand und Sie erhalten die Ausgabe, ohne sich um den Rest des Prozesses kümmern zu müssen.

Sopalajo de Arrierez
quelle
34

Eine Möglichkeit besteht darin, einen falschen "sudo" -Befehl mit folgendem Inhalt zu erstellen:

#!/usr/bin/bash

"$@"

Dies ermöglicht die install.sh um fortzufahren, weil sudo gefunden wird.

Dies erhöht nicht die Rechte, wie dies bei echtem Sudo der Fall ist. Wenn Sie wirklich erweiterte Rechte benötigen, starten Sie cygwin shell mit einem Konto mit Administratorrechten (XP) oder klicken Sie mit der rechten Maustaste auf cygwin.bat und "Als Administrator ausführen" (Vista, Win7)

Peon
quelle
5
Nur aus Neugier von jemandem, der nicht fließend spricht bash: Warum funktioniert das? Die Manpage sagt nichts darüber $@ irgendetwas tun sudo -mögen. Stattdessen handelt es sich nur um Argumente für das Skript. Und wären die Anführungszeichen in diesem Fall nicht überflüssig? Andernfalls, wenn Sie a tun würden sudo foo bar dann versucht es auszuführen "foo bar" als einzelner Befehl, der angesichts der irrationalen Angst vor Leerzeichen auf UNIX-ähnlichen Systemen wahrscheinlich nicht existiert.
Joey
7
@Johannes: "$@" (wenn in Anführungszeichen gesetzt) ​​funktioniert anders als "$*": es erweitert sich zu einem trennen Wort für jede Positionsvariable. Beispiel: Ob $1 == "foo bar" und $2 == "baz", dann "$@" ist "foo bar" baz - ein Wort für jeden Parameter (im Gegensatz zu "$*", was in ... resultiert "foo bar baz" als ein Wort). Siehe Handbuch von bash, Sektion Parameter Unterabschnitt Spezielle Parameter . Das Endergebnis von Peons Skript ist, dass es seine Argumente genau so ausführt, wie sie übergeben wurden.
grawity
1
Ach ja ok Und woher kommt das sudo Teil hereinkommen? Das obige Snippet tut nichts aus der Ferne in diese Richtung, oder?
Joey
2
@Johannes: In Unix ein echter sudo würde Privilegien von sterblichen erhöhen root bevor Sie den Befehl ausführen. In Cygwin gibt es so etwas nicht, also Peons gefälschtes Drehbuch (das du benennen sollst) sudo ) führt den Befehl nur direkt aus, ohne seine Berechtigungen zu ändern. (Dies bedeutet, dass Sie möglicherweise ausführen müssen ./install.sh als Administrator.)
grawity
2
@grawity: runas Sollte dies funktionieren, ist es nicht auf die Benutzerkontensteuerung angewiesen und fordert von sich aus zur Eingabe eines Kennworts auf. Ich war nur verwirrt, warum das Skript in der Antwort anscheinend nicht das tat, was der Name andeutete, von dem ich annahm, dass es das Ziel war. Entschuldigung für meine Dummheit ;-)
Joey
21

Ich fand die Antwort auf die cygwin mailing liste . Zu rennen command mit erhöhten Rechten in Cygwin, stellen Sie dem Befehl mit cygstart --action=runas so was:

$ cygstart --action=runas command

Daraufhin wird ein Windows-Dialogfeld geöffnet, in dem Sie nach dem Administratorkennwort gefragt werden. Führen Sie den Befehl aus, wenn das richtige Kennwort eingegeben wurde.

Dies ist leicht zu skripten, solange ~/bin ist auf deinem Weg:

$ cat ~/bin/sudo
#!/usr/bin/bash
cygstart --action=runas "$@"

$ PATH=$HOME/bin:$PATH
$ chmod +x ~/bin/sudo
$ sudo elevatedCommand

Getestet unter 64-Bit Windows 8.

dotancohen
quelle
5
Das Problem mit dem cygstart Methode ist, dass es nur für Windows-Befehle / Programme funktioniert. Du kannst nicht tun sudo ls. SUDO für CygWin ist ordentlich, aber es fehlen noch einige gute sudo Befehl drin.
Sopalajo de Arrierez
Vielen Dank, Sopalajode. In welcher Situation mussten Sie verwenden sudo ls in Cygwin?
dotancohen
3
Oh nein, @Dotancohen, es war nur ein Beispiel. Sie können verwenden sudo für CygWin, um einen Windows- oder CygWin-Befehl auszuführen. Es ist sehr nützlich für mich. Aber die praktischere Methode, die ich gefunden habe, ist dieser Skript-Wrapper für SUDO für CygWin, den ich entwickelt habe: superuser.com/questions/741345/… (noch in der Beta, scheint aber zu funktionieren). Damit können Sie bequem Dinge wie bestellen sudo net start vncserver.
Sopalajo de Arrierez
@SopalajodeArrierez: Das ist absolut großartig! Vielen Dank für den Beitrag und den Link.
dotancohen
seltsamerweise streift dies aus /bin und /usr/bin von dem PATH. Es ruft erfolgreich emacs auf: ShellExecute(NULL, "runas", "C:\cygwin64\bin\emacs-w32.exe", "(null)", "(null)", 1) aber dann kann emacs nicht finden ls für z. M-x dired, auch nach interaktiver Wiederherstellung des PATH mit (setenv ...). Gibt es hier ein Problem mit vertrauenswürdigen Pfaden?
BaseZen
5

Aufbauend auf Dotancohens Antwort Ich verwende einen Alias:

alias sudo="cygstart --action=runas"

Funktioniert wie ein Zauber für externe Programme (allerdings nicht für Shell-Einbauten):

sudo chown User:Group <file>
thoni56
quelle
3

Sudo (Elevate) für Windows ™

Ich arbeite viel an der Befehlszeile in Windows ™.

In Cygwin selbst glaube ich, dass Sie einen root-Befehl mit ausführen können su -c /the/cmd Was Sudo selbst innerhalb des Windows ™ -Dateisystems anbelangt, indem die Berechtigungen des Benutzers über die Befehlszeile erhöht werden. Wenn Sie Administrator sind, funktioniert dies hervorragend für Sie. Ansonsten benutze runas und hol dir den Admin-Pass;).

Jetzt kann ich mich nicht erinnern, woher wir diesen Code haben, aber hier ist er. Ich hoffe, es hilft.

Übrigens war das Paket, mit dem wir das kompilieren gcc-mingw32.

$ i586-mingw32msvc-gcc sudo.c -o sudo.exe
# Put sudo.exe in /usr/bin or in your windows path (%homedrive%\windows)
#example:
$ sudo vi /cygdrive/c/windows/system32/drivers/etc/hosts

/**
* (sudo for Windows™)
* @filename sudo.c
*/
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <shellapi.h>
#include <wchar.h>


LPWSTR *mergestrings(LPWSTR *left, LPCWSTR right)
{
    size_t size = ( 1 + lstrlen(*left) + lstrlen(right) ) * sizeof(LPWSTR*);
    if ( *left ) {
        LPWSTR leftcopy = _wcsdup(*left);
        *left = (LPWSTR)realloc(*left, size);
        *left = lstrcpy(*left, leftcopy);
        *left = lstrcat(*left, right);
        free( leftcopy );
    }
    else
        *left = _wcsdup(right);
    return left;
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpcommand, int nShowCmd)
{
    DWORD result = 0x2a;
    LPWSTR *argv = NULL;
    int argc = 0;
    if ( argv = CommandLineToArgvW(GetCommandLineW(), &argc) ) {
        if ( argc < 2 ) {
            LPWSTR usagemsg = NULL;
            usagemsg = *mergestrings(&usagemsg, argv[0]);
            usagemsg = *mergestrings(&usagemsg, TEXT(" <command_to_run> [arguments]"));
            MessageBox(NULL, usagemsg, TEXT("Usage:"), MB_OK | MB_ICONEXCLAMATION );
            LocalFree( argv );
            free( usagemsg );
            return ERROR_BAD_ARGUMENTS;
        }
        else {
            LPWSTR command = argv[1];
            LPWSTR arguments = NULL;
            int c;
            for ( c = 2; c < argc; c++ ) {
                arguments = *mergestrings(&arguments, argv[c]);
                arguments = *mergestrings(&arguments, TEXT(" "));
            }
            result = (DWORD)ShellExecute(NULL, TEXT("runas"), command, arguments, NULL, SW_SHOWNORMAL);
            LocalFree( argv );
            if ( arguments )
                free( arguments );
            switch ( result )
            {
                case 0:
                    result = ERROR_OUTOFMEMORY;
                    break;

                case 27:
                case 31:
                    result = ERROR_NO_ASSOCIATION;
                    break;

                case 28:
                case 29:
                case 30:
                    result = ERROR_DDE_FAIL;
                    break;
                case 32:
                    result = ERROR_DLL_NOT_FOUND;
                    break;
                default:
                    if ( result > 32 )
                        result = 0x2a;
            }
        }
    }
    else
        result = GetLastError();

    if (result != 0x2a) {
        LPWSTR errormsg = NULL;
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
                      NULL, result, 0, (LPWSTR)&errormsg, 0, NULL);
        MessageBox(NULL, errormsg, TEXT("Error:"), MB_OK | MB_ICONERROR);
        LocalFree( errormsg );
        return result;
    }
    else
        return NO_ERROR;
}
tao
quelle
5
Dieser Code ist schrecklich. Es ist voller Fehler, wie beispielsweise den Rückgabewert von realloc () nicht zu überprüfen, bevor dereferenziert oder sizeof (LPWSTR *) statt sizeof (* LPWSTR) geschrieben wird, wobei LPWSTR ein Zeigertyp zu sein scheint und man die Größe eines Zeichens abrufen möchte, nicht die Größe des Zeigers. Darüber hinaus ist völlig unklar, warum z. Fall 29 führt zu ERROR_DDE_FAIL. Können Sie aus dem Code schließen, warum? Ich kann nicht und ich denke, jemand anderes kann es auch nicht. Bitte posten Sie diesen Code in Zukunft nicht mehr.
4
@ Mattew: Bitte helfen Sie der Community in Zukunft, indem Sie eine bereinigte Version des Code-Snippets veröffentlichen, das Ihnen nicht gefällt.
Erik Allik
Code sollte nicht auf Superuser sein. Stellen Sie es auf codereview.se und verlinken Sie es einfach von hier.
Ben Voigt
@ user185282: Gute Punkte. Ich habe die Antwort abgelehnt.
unforgettableid
Lieber Tao: Sie haben geschrieben: "Ich kann mich nicht erinnern, woher wir diesen Code haben". Haben Sie diesen Code geschrieben oder hat ihn jemand anders geschrieben?
unforgettableid
2

Eine leichte Verbesserung gegenüber Peon's gefälschtes Sudo Skript:

#!/bin/sh
# Drop any option arguments.
while [[ $# -ge 0 && $1 = -* ]]; do
  shift
done

"$@"

Dieses Skript löscht im Hintergrund alle an sudo übergebenen Optionen und führt den Befehl aus (ohne die Berechtigungen tatsächlich zu erhöhen). Das Löschen der Optionen verbessert die Kompatibilität etwas. Ein vollständigeres Wrapper-Skript sollte Optionen genau wie sudo analysieren.

Anstatt zu versuchen, sudo durch einen Wrapper zu ersetzen, der dies tut cygstart --action=runas "$@"Verwenden Sie einfach diese einfache gefälschtes Sudo Erstellen Sie einen Wrapper und führen Sie das Installationsskript selbst (oder was auch immer Sie ausführen möchten, das sudo verwendet) mit erhöhten Rechten aus.

Gene Pavlovsky
quelle