Cygwin中没有“ sudo”命令


41

因为Cygwin中没有sudo命令,所以我要运行的脚本失败了

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

解决此问题的标准方法是什么?编辑脚本删除sudo?是否有一些sudo类似Windows的工具?


@dotancohen,我希望我选对了一个。
杰森·桑德拉姆

看起来对我来说是一个很好的解决方案!在过去的五年中,Cygwin的支持肯定有所改善!
dotancohen


@Benj,我想知道为什么这个问题也没有在这里得到解决。
杰森·桑德拉姆

确实是@JasonSundram。让我知道答案是否移动,然后我将更新链接。

Answers:


8

我为CygWinSUDO编写了(相当简单的)TOUACExt,这是一种beta版的shell脚本自动化程序,可以实现Linux 的经典行为 sudo

  • 必要时自动打开和关闭 sudoserver.py。
  • 请求UAC高程提示。

安装需要将这四个.sh脚本复制到某个路径目录,创建别名以及该线程中详细介绍的其他几个步骤。

结果:键入单个即可sudo YourCommand获取输出,而不必担心其余过程。


35

一种方法是使用以下内容创建伪造的“ sudo”命令:

#!/usr/bin/bash

"$@"

install.sh因为找到了sudo,这将允许继续进行。

这不会像真正的sudo那样提升特权。如果您确实需要提升的特权,请从具有管理特权(XP)的帐户启动cygwin shell,或右键单击cygwin.bat并“以管理员身份运行”(Vista,Win7)


5
只是出于好奇,一个不流利的人说bash:为什么这样做有效?该联机帮助页未提及$@任何操作sudo-例如。相反,它只是脚本的所有参数。在这种情况下,周围的引号会不会是多余的?否则,如果您这样做,sudo foo bar则它会尝试"foo bar"作为单个命令执行,鉴于对类UNIX系统上空间的非理性恐惧,该命令可能不存在。
乔伊

7
@Johannes :("$@"在双引号中)的工作方式与"$*":不同:它为每个位置变量扩展为一个单独的词。示例:如果$1 == "foo bar"$2 == "baz""$@"则为"foo bar" baz-每个参数一个单词(与不同"$*",结果"foo bar baz"为一个单词)。参见手册中bash,部分参数,该款特殊参数。Peon脚本的最终结果是它完全按照传递的参数执行参数。
grawity 2010年

1
喔好吧。和哪里的sudo一部分进来吗?在摘要上方,该方向没有做任何远程操作,对吗?
乔伊

2
@Johannes:在Unix中,实数sudoroot在运行命令之前将特权从普通提升为。在Cygwin中,没有这样的事情,因此Peon的伪脚本(您应该命名为sudo)仅在不更改其特权的情况下直接运行该命令。(这意味着您可能需要以./install.sh管理员身份运行。)
grawity 2010年

2
@grawity:runas应该起作用,它不依赖于UAC,而是自动提示输入密码。我只是感到困惑,为什么答案中的脚本显然没有按照我认为的目标来暗示名称。对不起,我很愚蠢;-)
乔伊(Joey)2010年

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。CygWin的SUDO很简洁,但是仍然缺少一些好的sudo命令。
Sopalajo de Arrierez 2014年

谢谢你,Sopalajode。在什么情况下需要sudo ls在Cygwin中使用?
dotancohen 2014年

3
哦,不,@ Dotancohen,这只是一个例子。您可以使用sudoCygWin运行任何Windows或CygWin命令。这对我来说是非常有用的。但是,我发现的更实用的方法是为我开发的CygWin的SUDO编写此脚本包装:superuser.com/questions/741345/…(仍处于Beta中,但似乎可以使用)。有了它,您可以轻松点菜sudo net start vncserver
Sopalajo de Arrierez 2014年

@SopalajodeArrierez:太棒了!感谢您的帖子和链接。
dotancohen 2014年

奇怪的是,这种剔除/bin/usr/binPATH。它确实成功调用了emacs:ShellExecute(NULL, "runas", "C:\cygwin64\bin\emacs-w32.exe", "(null)", "(null)", 1)但是,即使使用交互式还原PATH之后,emacs也无法找到ls例如。这里是否存在受信任的路径问题?M-x dired(setenv ...)
BaseZen

5

基于dotancohen的答案,我正在使用别名:

alias sudo="cygstart --action=runas"

可以作为外部程序的魅力(尽管不是内置的shell):

sudo chown User:Group <file>

3

Windows™的Sudo(提升)

我在Windows™中的命令行上做了很多工作。

在Cygwin本身中,我相信您可以su -c /the/cmd在Windows™文件系统中以sudo本身的身份运行root命令,以从命令行提升用户的权限。如果您是管理员,这将非常适合您。否则,请使用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
这段代码很糟糕。这充满了很多错误,例如在取消引用或写入sizeof(LPWSTR *)而不是sizeof(* LPWSTR)之前不检查realloc()的返回值,其中LPWSTR似乎是一种指针类型,并且您想要检索一个字符的大小,而不是指针的大小。此外,还不清楚为什么案例29导致ERROR_DDE_FAIL。您可以从代码中得出结论吗?我做不到,我猜别人也做不到。请不要在将来发布此类代码。

4
@Mattew:请将来通过发布您不喜欢的代码片段的清理版本来帮助社区。
Erik Allik 2013年

代码不应位于超级用户上。将其放在codereview.se上,然后从此处链接即可。
Ben Voigt 2014年

@ user185282:好点。我拒绝了答案。
难忘的

亲爱的陶:您写道:“我不记得我们从何处获得此代码”。您是编写此代码还是其他人编写的?
难忘的

2

Peon的伪sudo脚本略有改进:

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

"$@"

该脚本会静默删除传递给sudo的所有选项,并执行命令(实际上不会提升特权)。删除选项可以在某种程度上改善兼容性。实际上,更完整的包装器脚本应该以与sudo相同的方式解析选项。

与其尝试用一个可替代的sudo包装器代替sudo,不如cygstart --action=runas "$@"使用这个简单的假sudo包装器并以提升的特权运行安装脚本本身(或您尝试运行的使用sudo的任何脚本)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.