У Cygwin немає команди «sudo»


41

Оскільки в Cygwin немає команди sudo , сценарії, з якими я хочу запустити, не спрацьовують

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

Який стандартний спосіб подолати це? Редагування скриптів для видалення sudo? Отримаєте якийсь sudoподібний інструмент для Windows?


@dotancohen, сподіваюся, я вибрав правильний.
Джейсон Сундрам

Виглядає як гарне рішення для мене! Підтримка Cygwin напевно покращилася за останні п’ять років!
dotancohen


@Benj, мені цікаво, чому це питання теж не мігрувало сюди.
Джейсон Сундрам

@JasonSundram справді. Повідомте мене, якщо відповідь буде перенесено, я потім оновлюю посилання.
Бендж

Відповіді:


8

Я написав (досить простий) TOUACExt для SUDO для CygWin , попередню бета-версію сценарію оболонки, яка підходить до поведінки класичного sudo для Linux:

  • Відкривається та закривається автоматично sudoserver.py при необхідності.
  • Запит на підказку для підйому UAC

Встановлення вимагає копіювання чотирьох .shскриптів у деяку каталог шляху, створення псевдоніма та ще кілька кроків, детально описаних у потоці.

Результати : ви вводите сингл sudo YourCommandі отримуєте вихід з нього, не турбуючись про інший процес.


35

Один із способів - створити підроблену команду "sudo" із наступним вмістом:

#!/usr/bin/bash

"$@"

Це дозволить install.shпродовжувати, тому що знайдено судо.

Це не підвищує привілеїв, як це справжнє судо. Якщо вам справді потрібні підвищені привілеї, запустіть оболонку cygwin з облікового запису з адміністративними привілеями (XP) або r натисніть на cygwin.bat і «запустіть як адміністратор» (Vista, Win7)


5
Тільки з цікавості у того, хто не говорить вільно bash: Чому це працює? Сторінка не говорить про $@те, що робити щось подібне sudo. Натомість це просто всі аргументи до сценарію. І чи не були б цитати навколо нього зайвими в такому випадку? Інакше, якщо ви зробите це, sudo foo barто він намагається виконати "foo bar"як єдину команду, яка, ймовірно, не існує, враховуючи той ірраціональний страх перед пробілами в UNIX-подібних системах.
Joey

7
@Johannes: "$@"(при подвійному цитуванні) працює інакше "$*": розширюється на окреме слово для кожної позиційної змінної. Приклад: Якщо $1 == "foo bar"і $2 == "baz", то "$@"є "foo bar" baz- одне слово для кожного параметра (на відміну від "$*", яке призводить до "foo bar baz"одного слова). Дивіться посібник bash, розділ Параметри , підрозділ Спеціальні параметри . Кінцевим результатом сценарію Пеона є те, що він виконує свої аргументи точно так, як вони були передані.
grawity

1
Ну, тоді добре. І куди sudoвходить частина? Вище фрагмент не робить нічого віддаленого в цьому напрямку, правда?
Joey

2
@Johannes: У Unix справжній sudoпідніме привілеї від смертних до того, rootяк запустити команду. У Cygwin такого немає, тому підроблений сценарій Пеона (який ви повинні назвати sudo) просто виконує команду безпосередньо, не змінюючи своїх привілеїв. (Це означає, що вам може знадобитися працювати ./install.shадміністратором.)
grawity

2
@grawity: runasмає працювати, він не покладається на UAC і сам вимагає ввести пароль. Мене просто збентежило, чому сценарій у відповіді, очевидно, не робив того, що мав на увазі ім'я, яке я припускав, що це було. Вибачте за мою дурість ;-)
Joey

21

Я знайшов відповідь у списку розсилки cygwin . Для запуску commandз підвищеними привілеями в Cygwin передуйте команді cygstart --action=runasтак:

$ cygstart --action=runas command

Це відкриє діалогове вікно Windows із запитом пароля адміністратора та запустить команду, якщо введено правильний пароль.

Це легко скриптується, якщо ви ~/binна вашому шляху:

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

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

Тестується на 64-розрядної Windows 8.


5
Проблема cygstartметоду полягає в тому, що він працює лише для команд / програм Windows. Не можна робити sudo ls. SUDO для CygWin охайний, але все ще не має sudoв ньому гарної команди.
Sopalajo de Arrierez

Дякую, Сопалайоде. У якій ситуації вам потрібно було користуватися sudo lsCygwin?
dotancohen

3
О, ні, @Dotancohen, це був лише приклад. Ви можете використовувати sudoдля CygWin для запуску будь-якої команди Windows або CygWin. Це дуже корисно для мене. Але більш практичний метод, який я знайшов, - це розгортання сценарію для SUDO для CygWin, який я розробив: superuser.com/questions/741345/… (все ще в бета-версії, але, здається, працює). З його допомогою ви можете зручно замовляти подібні речі sudo net start vncserver.
Sopalajo de Arrierez

@SopalajodeArrierez: Це абсолютно приголомшливо! Дякую за повідомлення та посилання.
dotancohen

Цікаво, що це викреслює /binі /usr/binз PATH. Він успішно викликає emacs: ShellExecute(NULL, "runas", "C:\cygwin64\bin\emacs-w32.exe", "(null)", "(null)", 1)але потім emacs не може знайти, lsнаприклад M-x dired, навіть після інтерактивного відновлення використання PATH (setenv ...). Чи є тут питання щодо довірених шляхів?
BaseZen

5

Спираючись на відповідь dotancohen, я використовую псевдонім:

alias sudo="cygstart --action=runas"

Працює як шарм для зовнішніх програм (але не вбудовані оболонки):

sudo chown User:Group <file>

3

Судо (ліфт) для Windows ™

Я багато працюю над командним рядком в Windows ™.

В самому Cygwin я вважаю, що ви можете запустити кореневу команду su -c /the/cmdяк для sudo себе в файловій системі Windows ™, піднімаючи дозволи користувача з командного рядка. Якщо ви адміністратор, це буде чудово для вас. В іншому випадку використовуйте руни і отримуйте пропуск адміністратора;).

Зараз я не можу згадати, звідки у нас цей код, але ось він. Я сподіваюся, що це допомагає.

До речі, пакет, який ми використовуємо для складання цього, був 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;
}

5
Цей код жахливий. Він повний помилок, таких як не перевірка значення повернення realloc () перед перенаправленням або записом sizeof (LPWSTR *) замість sizeof (* LPWSTR), де LPWSTR здається типом вказівника і хоче отримати розмір одного символу, а не розмір вказівника. Крім того, абсолютно незрозуміло, чому, наприклад, випадок 29 призводить до ERROR_DDE_FAIL. Чи можете ви зробити висновок з коду, чому? Я не можу, і, мабуть, ніхто інший теж не може. Будь ласка, не публікуйте такий код у майбутньому.

4
@Mattew: надалі допоможіть спільноті, розмістивши очищену версію фрагмента коду, який вам не подобається.
Ерік Аллик

Код не повинен бути надрукованим. Помістіть його на codereview.se та просто посилання звідси.
Ben Voigt

@ user185282: Гарні моменти. Я спростував відповідь.
незабутній

Шановний дао: Ви писали: "Не можу згадати, де у нас цей код". Ви написали цей код чи хтось його ще написав?
незабутній

2

Невелике поліпшення сценарію фальшивого судо Пеона :

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

"$@"

Цей скрипт мовчки скидає будь-які параметри, передані для sudo та виконує команду (фактично не підвищуючи привілеї). Скасування параметрів дещо покращує сумісність. Більш повний сценарій обгортки насправді повинен розбирати параметри так само, як це робить sudo.

Замість того, щоб намагатися замінити sudo на обгортку, яка є cygstart --action=runas "$@", просто використовуйте цю просту фальшиву обгортку sudo та запустіть свій інсталяційний скрипт (або все, що ви намагаєтеся запустити, використовуючи sudo) з підвищеними привілеями.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.