В Cygwin нет команды sudo

41

Поскольку в Cygwin нет команды sudo , сценарии, с которыми я хочу работать, не работают

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

Какой стандартный способ обойти это? Редактирование скриптов для удаления sudo? Приобретаете какой-нибудь sudoпохожий инструмент для Windows?

Джейсон Сундрам
источник
@dotancohen, надеюсь, я выбрал правильный.
Джейсон Сундрам
Похоже, хорошее решение для меня! Поддержка Cygwin стала лучше за последние пять лет!
Dotancohen
@ Бендж, мне интересно, почему этот вопрос тоже не перенесся сюда.
Джейсон Сундрам,
@JasonSundram действительно. Дайте мне знать, если ответ будет перенесен, я обновлю ссылку.
Бендж

Ответы:

8

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

  • Открывается и закрывается автоматически sudoserver.py при необходимости.
  • Запрашивает UAC Elevation Prompt.

Для установки требуется скопировать четыре .shсценария в какой-либо каталог пути, создать псевдоним и еще несколько шагов, подробно описанных в теме.

Результаты : вы набираете один sudo YourCommandи получаете его результат, не беспокоясь об остальной части процесса.

Сопалахо де Арриерес
источник
35

Один из способов - создать поддельную команду «sudo» со следующим содержимым:

#!/usr/bin/bash

"$@"

Это позволит install.shпродолжить, потому что sudo найден.

Это не повышает привилегии, как это делает настоящий sudo. Если вам действительно нужны повышенные привилегии, запустите оболочку Cygwin с учетной записью с правами администратора (XP) или щелкните правой кнопкой мыши на cygwin.bat и «запустите от имени администратора» (Vista, Win7)

поденщик
источник
5
Просто из любопытства кого-то, кто не говорит бегло bash: почему это работает? На странице руководства ничего не говорится о том, $@чтобы что- то делать sudo. Вместо этого это всего лишь аргументы сценария. И разве цитаты вокруг этого не будут лишними в этом случае? В противном случае, если вы сделаете a, sudo foo barон попытается выполнить "foo bar"как одну команду, которая, вероятно, не существует, учитывая этот иррациональный страх перед пробелами в UNIX-подобных системах.
Джои
7
@Johannes: "$@"(в двойных кавычках) работает иначе, "$*"чем в отдельном слове для каждой позиционной переменной. Пример: если $1 == "foo bar"и $2 == "baz", то "$@"есть "foo bar" baz- одно слово для каждого параметра (в отличие "$*", что приводит "foo bar baz"к одному слову). См. Руководство bash, раздел Параметры , подраздел Специальные параметры . Конечный результат сценария Peon заключается в том, что он выполняет свои аргументы в точности так, как они были переданы.
Гравитация
1
Ах хорошо. И где sudoчасть входит? Выше фрагмент не делает ничего удаленно в этом направлении, верно?
Джои
2
@Johannes: в Unix реальный sudoподнимет привилегии от смертных до rootдо запуска команды. В Cygwin такого нет, поэтому поддельный скрипт Peon (который вы должны назвать sudo) просто запускает команду без изменения ее привилегий. (Это означает, что вам может потребоваться работать ./install.shот имени администратора.)
grawity
2
@grawity: runasдолжно работать, оно не зависит от UAC и запрашивает пароль само по себе. Я был просто смущен, почему сценарий в ответе, очевидно, не сделал то, что подразумевалось под названием, которое я считал целью. Извините за мою глупость ;-)
Джои
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.

dotancohen
источник
5
Проблема cygstartметода заключается в том, что он работает только для команд / программ Windows. Вы не можете сделать sudo ls. SUDO для CygWin аккуратен, но в нем все еще нет хорошей sudoкоманды.
Сопалахо де Арриерес
Спасибо, Сопалайод. В какой ситуации вам нужно было использовать sudo lsCygwin?
dotancohen
3
О, нет, @Dotancohen, это был просто пример. Вы можете использовать sudoCygWin для запуска любой команды Windows или CygWin. Это очень полезно для меня. Но более практичный метод, который я нашел, - это скрипт-оболочка для SUDO для CygWin, который я разработал: superuser.com/questions/741345/… (все еще в бета-версии, но, похоже, работает). С его помощью вы можете удобно заказать такие вещи, как sudo net start vncserver.
Сопалахо де Арриерес
@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>
thoni56
источник
3

Sudo (Elevate) для Windows ™

Я много работаю над командной строкой в ​​Windows ™.

Я считаю, что в самом Cygwin вы можете запускать команду root с помощью su -c /the/cmdas для самого sudo в файловой системе Windows ™, повышая права пользователя из командной строки. Если вы являетесь администратором, это отлично подойдет для вас. В противном случае используйте runas и получите пароль администратора;).

Сейчас я не могу вспомнить, откуда у нас этот код, но вот он. Я надеюсь, что это помогает.

Кстати, пакет, который мы используем для компиляции, был 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 и просто свяжите здесь.
Бен Фойгт
@ user185282: Хорошие моменты. Я понизил ответ.
незабываемый
Уважаемый Дао: Вы написали: «Я не могу вспомнить, откуда у нас этот код». Вы написали этот код, или кто-то другой написал его?
незабываемый
2

Небольшое улучшение по батрак в поддельной SUDO сценария:

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

"$@"

Этот скрипт молча отбрасывает все параметры, переданные в sudo, и выполняет команду (фактически не повышая привилегии). Отбрасывание опций несколько улучшает совместимость. Более полный скрипт-обертка должен фактически анализировать параметры так же, как это делает sudo.

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

Ген павловский
источник