Tidak ada perintah 'sudo' di Cygwin

41

Karena tidak ada perintah sudo di Cygwin , skrip yang ingin saya jalankan gagal

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

Apa cara standar untuk mengatasi ini? Mengedit skrip untuk dihapus sudo? Mendapatkan beberapa sudoalat seperti Windows?

Jason Sundram
sumber
@dotancohen, saya harap saya memilih yang tepat.
Jason Sundram
Sepertinya solusi yang bagus untuk saya! Dukungan Cygwin sudah pasti membaik dalam lima tahun terakhir!
dotancohen
@ Benj, saya bertanya-tanya mengapa pertanyaan itu tidak dimigrasi ke sini juga.
Jason Sundram
@JasonSundram memang. Beri tahu saya jika jawabannya dipindahkan, kemudian saya akan memperbarui tautan.
Benj

Jawaban:

8

Saya menulis TOUACExt (agak sederhana) untuk SUDO untuk CygWin , otomatisasi skrip shell pra-beta yang mendekati perilaku klasik sudo untuk Linux:

  • Buka dan tutup secara otomatis sudoserver.py saat diperlukan.
  • Meminta UAC Elevation Prompt.

Instalasi memerlukan penyalinan empat .shskrip ke beberapa direktori jalur, membuat alias dan hanya beberapa langkah lebih rinci dalam utas.

Hasilnya : Anda mengetikkan satu sudo YourCommanddan Anda mendapatkan outputnya, tanpa harus khawatir tentang sisa proses.

Sopalajo de Arrierez
sumber
35

Salah satu caranya adalah dengan membuat perintah "sudo" palsu dengan konten berikut:

#!/usr/bin/bash

"$@"

Ini akan memungkinkan install.shuntuk melanjutkan, karena sudo ditemukan.

Ini tidak meningkatkan hak istimewa seperti sudo nyata. Jika Anda benar-benar memerlukan hak istimewa yang ditingkatkan mulailah dengan cygwin shell dari akun dengan hak administratif (rp) atau klik-r pada cygwin.bat dan "jalankan sebagai administrator" (Vista, Win7)

Prajurit infanteri
sumber
5
Hanya karena penasaran dari seseorang yang tidak lancar berbicara bash: Mengapa ini berhasil? Halaman manual tidak mengatakan apa-apa tentang $@melakukan sesuatu sudoseperti. Alih-alih itu hanya argumen untuk skrip. Dan bukankah kutipan di sekitarnya akan berlebihan dalam kasus itu? Kalau tidak, jika Anda akan melakukan sudo foo barmaka ia mencoba mengeksekusi "foo bar"sebagai perintah tunggal yang mungkin tidak ada mengingat ketakutan irasional ruang pada sistem seperti UNIX.
Joey
7
@Johannes: "$@"(ketika dikutip ganda) bekerja berbeda dari "$*": itu diperluas ke kata yang terpisah untuk setiap variabel posisi. Contoh: Jika $1 == "foo bar"dan $2 == "baz", kemudian "$@"adalah "foo bar" baz- satu kata untuk setiap parameter (tidak seperti "$*", yang menghasilkan "foo bar baz"satu kata). Lihat manual bash, bagian Parameter , subbagian Parameter khusus . Hasil akhir dari skrip Peon adalah bahwa ia mengeksekusi argumennya persis seperti yang disahkan.
grawity
1
Ah, baiklah. Dan di mana sudobagian itu masuk? Cuplikan di atas tidak melakukan apa pun dari jarak jauh ke arah itu, kan?
Joey
2
@ Johnannes: Di Unix, yang asli sudoakan meningkatkan hak istimewa dari manusia rootsebelum menjalankan perintah. Di Cygwin, tidak ada hal seperti itu, jadi skrip palsu Peon (yang seharusnya Anda sebutkan sudo) hanya menjalankan perintah secara langsung tanpa mengubah hak istimewanya. (Ini berarti Anda mungkin perlu menjalankan ./install.shsebagai Administrator.)
grawity
2
@grawity: runasharus berfungsi, tidak bergantung pada UAC dan meminta kata sandi dengan sendirinya. Saya hanya bingung mengapa naskah dalam jawaban itu ternyata tidak melakukan apa yang tersirat nama yang saya anggap tujuannya. Maaf atas kebodohan saya ;-)
Joey
21

Saya menemukan jawabannya di milis cygwin . Untuk menjalankan commanddengan hak istimewa yang lebih tinggi di Cygwin, awali perintah dengan cygstart --action=runasseperti ini:

$ cygstart --action=runas command

Ini akan membuka kotak dialog Windows yang meminta kata sandi Admin dan menjalankan perintah jika kata sandi yang tepat dimasukkan.

Ini mudah ditulis, asalkan ~/binada di jalur Anda:

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

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

Diuji pada Windows 8 64-bit.

dotancohen
sumber
5
Masalah dengan cygstartmetode ini adalah hanya berfungsi untuk perintah / program Windows. Anda tidak bisa melakukannya sudo ls. SUDO untuk CygWin rapi, tetapi masih kurang memiliki sudoperintah yang baik di dalamnya.
Sopalajo de Arrierez
Terima kasih, Sopalajode. Dalam situasi apa Anda perlu menggunakan sudo lsCygwin?
dotancohen
3
Oh, tidak, @Dancancohen, itu hanya sebuah contoh. Anda dapat menggunakan sudountuk CygWin untuk menjalankan perintah Windows atau CygWin. Ini sangat berguna bagi saya. Tetapi metode yang lebih praktis yang saya temukan adalah pembungkus skrip ini untuk SUDO untuk CygWin yang saya kembangkan: superuser.com/questions/741345/… (masih dalam Beta, tetapi tampaknya berfungsi). Dengan itu Anda dapat dengan nyaman memesan hal-hal seperti sudo net start vncserver.
Sopalajo de Arrierez
@SopalajodeArrierez: Itu benar-benar hebat! Terima kasih atas kiriman dan tautannya.
dotancohen
anehnya, ini strip /bindan /usr/bindari PATH. Itu berhasil memanggil emacs: ShellExecute(NULL, "runas", "C:\cygwin64\bin\emacs-w32.exe", "(null)", "(null)", 1)tetapi kemudian emacs tidak dapat menemukan lsmisalnya M-x dired, bahkan setelah secara interaktif mengembalikan PATH menggunakan (setenv ...). Apakah ada masalah jalur tepercaya di sini?
BaseZen
5

Membangun jawaban dotancohen Saya menggunakan alias:

alias sudo="cygstart --action=runas"

Berfungsi sebagai daya tarik untuk program eksternal (bukan built-in shell):

sudo chown User:Group <file>
thoni56
sumber
3

Sudo (Tinggikan) untuk Windows ™

Saya melakukan banyak pekerjaan pada baris perintah di Windows ™.

Di Cygwin itu sendiri saya percaya Anda dapat menjalankan perintah root dengan su -c /the/cmduntuk sudo itu sendiri dalam sistem file Windows ™ meningkatkan izin pengguna dari baris perintah, Jika Anda seorang administrator, ini akan bekerja sangat baik untuk Anda. Kalau tidak, gunakan runas dan dapatkan pass admin;).

Sekarang saya tidak ingat di mana kami mendapat kode ini, tetapi ini dia. Saya harap ini membantu.

BTW, paket yang kami gunakan untuk mengkompilasi ini 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
sumber
5
Kode ini mengerikan. Penuh dengan kesalahan seperti tidak memeriksa nilai pengembalian realloc () sebelum dereferencing atau menulis sizeof (LPWSTR *) alih-alih sizeof (* LPWSTR) di mana LPWSTR tampaknya merupakan tipe penunjuk dan seseorang ingin mengambil ukuran satu karakter, bukan ukuran pointer. Selain itu, sama sekali tidak jelas mengapa mis. Kasus 29 mengarah ke ERROR_DDE_FAIL. Bisakah Anda menyimpulkan dari kode itu mengapa? Saya tidak bisa dan saya kira orang lain juga tidak bisa. Tolong, jangan memposting kode seperti itu di masa depan.
4
@Mattew: tolong di masa depan membantu komunitas dengan memposting versi potongan kode yang tidak Anda sukai.
Erik Allik
Kode tidak boleh berada di superuser. Letakkan di codereview.se, dan cukup tautkan dari sini.
Ben Voigt
@ user185282: Poin bagus. Saya telah menurunkan jawaban.
tak terlupakan
Dear tao: Anda menulis, "Saya tidak ingat dari mana kami mendapat kode ini". Apakah Anda menulis kode ini, atau apakah orang lain yang menulisnya?
tak terlupakan
2

Sedikit peningkatan pada naskah sudo palsu Peon :

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

"$@"

Script ini secara diam-diam menjatuhkan opsi apa pun yang diteruskan ke sudo dan mengeksekusi perintah (tanpa benar-benar meningkatkan hak istimewa). Menjatuhkan opsi agak meningkatkan kompatibilitas. Script wrapper yang lebih lengkap sebenarnya harus mengurai opsi dengan cara yang sama seperti sudo.

Alih-alih mencoba mengganti sudo dengan pembungkus yang berfungsi cygstart --action=runas "$@", gunakan saja pembungkus sudo palsu sederhana ini dan jalankan skrip instalasi Anda sendiri (atau apa pun yang Anda coba jalankan yang menggunakan sudo) dengan hak istimewa yang tinggi.

Gene Pavlovsky
sumber