Cygwin에는 'sudo'명령이 없습니다.


41

Cygwin 에는 sudo 명령 이 없으므로 실행하려는 스크립트가 실패합니다.

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

이 문제를 해결하는 표준 방법은 무엇입니까? 스크립트를 편집 제거하려면 sudo? 일부 얻기 sudoWindows 용 -like 도구를?


@ dotancohen, 나는 올바른 것을 고르기를 바랍니다.
Jason Sundram

나에게 좋은 해결책처럼 보인다! Cygwin 지원은 지난 5 년 동안 어느 정도 개선되었습니다!
dotancohen


@Benj, 왜 그 질문이 여기에서 마이그레이션되지 않았는지 궁금합니다.
Jason Sundram

@JasonSundram은 실제로. 답변이 이동하면 알려 주시면 링크를 업데이트하겠습니다.
Benj

답변:


8

필자는 Linux 의 고전적인 동작에 접근하는 사전 베타 쉘 스크립트 자동화 인 CygWinSUDO 용 TOUACExt를 작성했다 . sudo

  • 필요할 때 자동으로 sudoserver.py를 열고 닫습니다 .
  • UAC 고도 프롬프트를 요청합니다 .

설치 하려면 4 개의 .sh스크립트를 일부 경로 디렉토리에 복사하여 별명을 작성하고 스레드에 대해 몇 단계 만 더 수행하면됩니다.

결과 : 단일 sudo YourCommand프로세스를 입력하고 나머지 프로세스에 대해 걱정할 필요없이 결과를 얻습니다.


35

한 가지 방법은 다음 내용으로 가짜 "sudo"명령을 작성하는 것입니다.

#!/usr/bin/bash

"$@"

이것은 허용 할 install.shsudo를 찾을 수 있기 때문에, 계속.

이것은 실제 sudo처럼 권한을 높이 지 않습니다. 관리자 권한이 필요한 경우 관리자 권한 (XP) 계정으로 cygwin 셸을 시작하거나 cygwin.bat를 r- 클릭하고 " 관리자 권한으로 실행" (Vista, Win7)


5
유창하게 말하지 않는 누군가의 호기심에서 bash: 왜 이것이 효과가 있습니까? 맨 페이지는 비슷한 $@작업 에 대해 아무 말도하지 않습니다 sudo. 대신 스크립트에 대한 모든 주장입니다. 그리고 그 경우에 따옴표가 불필요하지 않습니까? 그렇지 않으면 UNIX와 같은 시스템의 공간에 대한 비합리적인 두려움 때문에 존재하지 않는 단일 명령으로 sudo foo bar실행하려고 시도 "foo bar"합니다.
Joey

7
@Johannes : "$@"(큰 따옴표로 묶인 경우)와 다르게 작동 합니다. 모든 위치 변수에 대해 별도의 단어로 "$*"확장됩니다 . 예 : 경우 와 다음 인 - (달리 각 파라미터에 대한 하나 개의 단어 , 결과 하나 단어). 수동 참조 섹션의 매개 변수 , 하위 특수 매개 변수 . Peon의 스크립트의 최종 결과는 전달 된대로 정확하게 인수를 실행한다는 것입니다. $1 == "foo bar"$2 == "baz""$@""foo bar" baz"$*""foo bar baz"bash
grawity

1
그래. 그리고 그 sudo부분은 어디에서 나오는가? 위의 스 니펫은 해당 방향으로 원격으로 아무것도하지 않습니다.
Joey

2
@Johannes : Unix에서 실제 sudoroot명령을 실행 하기 전에 필사자에서 특권을 올릴 것 입니다. Cygwin에는 그러한 것이 없으므로 Peon의 가짜 스크립트 (이름을 지정해야 함 sudo)는 권한을 변경하지 않고 명령을 직접 실행합니다. (이것은 ./install.sh관리자 로 실행해야 할 수도 있음을 의미합니다 .)
grawity

2
@ grawity : runas작동해야하며 UAC에 의존하지 않고 자체적으로 암호를 묻습니다. 나는 대답의 스크립트가 내가 목표라고 생각한 이름이 암시하는 것을하지 않은 이유를 혼란스럽게했습니다. 내 바보에 대해 죄송합니다 ;-)
Joey

21

cygwin 메일 링리스트 에서 답을 찾았습니다 . commandCygwin에서 높은 권한으로 실행하려면 다음 과 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. CygWin 용 SUDO는 깔끔하지만 여전히 좋은 sudo명령이 없습니다.
Sopalajo de Arrierez

Sopalajode 감사합니다. sudo lsCygwin에서 어떤 상황에서 사용해야 했습니까?
dotancohen

3
아뇨, @Dotancohen, 이것은 단지 예일뿐입니다. sudoCygWin에서 Windows 또는 CygWin 명령을 실행할 수 있습니다 . 그것은 나에게 매우 유용합니다. 그러나 내가 발견 한 더 실용적인 방법은 Cygwin에서 I에 대한 SUDO이 스크립트 래퍼 개발 : 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 는를 사용하여 PATH를 대화식으로 복원 한 후에도 ls예를 들어 찾을 수 없습니다 . 여기에 신뢰할 수있는 경로 문제가 있습니까? M-x dired(setenv ...)
BaseZen

5

dotancohen의 답변바탕 으로 별칭을 사용하고 있습니다.

alias sudo="cygstart --action=runas"

셸 내장이 아닌 외부 프로그램의 매력으로 작동합니다.

sudo chown User:Group <file>

3

Windows ™ 용 Sudo (Elevate)

Windows ™의 명령 행에서 많은 작업을 수행합니다.

Cygwin 자체에서는 su -c /the/cmdWindows ™ 파일 시스템 내에서 sudo 자체에 대해 루트 명령을 실행 하여 명령 행에서 사용자의 권한 을 높일 수 있다고 생각합니다 . 관리자 인 경우이 방법이 효과적입니다. 그렇지 않으면 runas를 사용하고 관리자의 패스를 가져옵니다.;).

이제 우리 가이 코드를 어디서 얻었는지 기억할 수 없지만 여기에 있습니다. 도움이 되길 바랍니다.

BTW, 이것을 컴파일하는 데 사용하는 패키지는 다음과 같습니다 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
이 코드는 끔찍합니다. LPWSTR이 포인터 유형 인 것처럼 보이고 한 문자의 크기를 검색하려는 경우 sizeof (* LPWSTR) 대신 sizeof (LPWSTR *)를 참조하거나 참조하기 전에 realloc ()의 반환 값을 확인하지 않는 것과 같은 오류로 가득합니다. 포인터의 크기 또한 사례 29가 ERROR_DDE_FAIL로 이어지는 이유는 확실하지 않습니다. 왜 코드에서 결론을 내릴 수 있습니까? 나는 할 수없고 다른 사람도 할 수없는 것 같아요. 앞으로 이러한 코드를 게시하지 마십시오.

4
@Mattew : 나중에 마음에 들지 않는 코드 스 니펫의 정리 된 버전을 게시하여 커뮤니티에 도움을주세요.
Erik Allik

코드는 수퍼 유저가 아니어야합니다. codereview.se에 넣고 여기에서 연결하십시오.
벤 Voigt

@ user185282 : 좋은 지적. 나는 대답을 downvoted했다.
잊을 수없는

친애하는 tao : 당신은 "우리가이 코드를 어디서 얻었는지 기억할 수 없습니다"라고 썼습니다. 이 코드를 작성 했습니까 아니면 다른 사람이 작성 했습니까?
잊을 수없는

2

Peon의 가짜 sudo 스크립트가 약간 개선되었습니다 .

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

"$@"

이 스크립트는 sudo로 전달 된 모든 옵션을 자동으로 삭제하고 실제로 권한을 높이 지 않고 명령을 실행합니다. 옵션을 삭제하면 호환성이 다소 향상됩니다. 보다 완전한 래퍼 스크립트는 실제로 sudo와 같은 방식으로 옵션을 구문 분석해야합니다.

sudo를 수행하는 래퍼로 바꾸는 대신 cygstart --action=runas "$@"이 간단한 가짜 sudo 래퍼를 사용하고 설치 스크립트 자체 (또는 sudo를 사용하여 실행하려는 모든 작업)를 높은 권한으로 실행하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.