Cygwinには「sudo」コマンドはありません


41

Cygwinにsudoコマンドがないため、実行したいスクリプトは失敗します

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

これを回避するための標準的な方法は何ですか?削除するスクリプトを編集しsudoますか?sudoWindows向けのツールを入手しますか?


@dotancohen、私は正しいものを選んだと思います。
ジェイソンスンドラム

私にとって良い解決策のように見えます!Cygwinのサポートは、過去5年間で確実に改善されました。
-dotancohen


@Benj、なぜその質問もここに移行されなかったのだろうか。
ジェイソンスンドラム

@JasonSundram確かに。答えが動いたら教えてください。リンクを更新します。
ベンジュ

回答:


8

Linux用の従来動作にアプローチするプレベータシェルスクリプトの自動化である、SUDO for CygWin用の(かなり単純な)TOUACExtを作成しました。 sudo

  • 必要に応じてsudoserver.pyを自動的に開閉します。
  • UAC標高プロンプトを要求します。

インストールには、4つの.shスクリプトを何らかのパスディレクトリにコピーし、エイリアスを作成し、スレッドに詳細な手順をいくつか追加する必要があります。

結果sudo YourCommand残りのプロセスを気にすることなく、シングルを入力してその出力を取得します。


35

1つの方法は、次の内容で偽の「sudo」コマンドを作成することです。

#!/usr/bin/bash

"$@"

install.shsudoが見つかったため、これにより続行できます。

これは、実際のsudoのように特権を昇格しません。昇格された特権が本当に必要な場合は、管理特権(XP)を持つアカウントからcygwinシェルを起動するか、cygwin.batをrクリックして「管理者として実行」(Vista、Win7)


5
流speakに話せない人からの好奇心から、bashなぜこれが機能するのですか?マンページには、何かをすることについて$@何も言われていない-のsudoように。代わりに、スクリプトに対するすべての引数のみです。そして、その場合の引用符はその場合には不必要ではないでしょうか?そうしないと、UNIXのようなシステム上のスペースに対する不合理な恐怖を考えると、おそらく存在しない単一のコマンドとしてsudo foo bar実行しようとし"foo bar"ます。
ジョーイ

7
@Johannes:("$@"二重引用符で囲まれている場合)とは動作が異なります。位置変数ごとに個別の単語に"$*"展開されます。例:場合とは、次にある-各パラメータの1つのワード(とは異なり、その結果で、一つの単語として)。マニュアルのセクションパラメータ、サブセクション特殊パラメータを参照してください。Peonのスクリプトの最終結果は、渡されたとおりに引数を実行することです。$1 == "foo bar"$2 == "baz""$@""foo bar" baz"$*""foo bar baz"bash
-grawity

1
ああ、わかった。そして、このsudo部品はどこから来ますか?上記のスニペットは、その方向にリモートでは何もしませんよね?
ジョーイ

2
@Johannes:Unixでは、実在のsudo特権rootはコマンドを実行する前に人間から特権に昇格します。Cygwinにはそのようなものはないので、Peonの偽のスクリプト(名前を付けますsudo)は、特権を変更せずにコマンドを直接実行するだけです。(これは./install.sh、管理者として実行する必要がある場合があることを意味します。)
grawity

2
@grawity:動作するrunasはずです。UACに依存せず、単独でパスワードを要求します。答えのスクリプトが、私が目的だと思っていた名前が暗示していることを明らかにしなかった理由を私はただ混乱させました。私の愚かさでごめんなさい;
ジョーイ

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コマンドがありません。
ソパラホデアリエレス14

ありがとう、ソパラジョード。sudo lsCygwinで使用する必要がある状況は何ですか?
dotancohen

3
ああ、いや、@ Dotancohen、それは単なる例でした。sudoCygWinを使用して、WindowsまたはCygWinコマンドを実行できます。それは私にとって非常に便利です。しかし、私が見つけたより実際的な方法は、私が開発したCygWin用SUDOのスクリプトラッパーです:superuser.com/questions/741345/…(まだベータ版ですが、動作しているようです)。それを使用すると、のようなものを快適に注文することができますsudo net start vncserver
ソパラホデアリエレス14

@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™のSudo(Elevate)

Windows™のコマンドラインで多くの作業を行っています。

Cygwin自体では、su -c /the/cmdWindows™ファイルシステム内で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
このコードはひどいです。LPWSTRがポインタ型であり、1つの文字のサイズを取得したいがポインターのサイズ。さらに、たとえばケース29がERROR_DDE_FAILにつながる理由は完全に不明です。なぜコードから結論づけることができますか?私にはできませんし、他の人にもできないと思います。今後、このようなコードを投稿しないでください。

4
@Mattew:将来的には、嫌いなコードスニペットのクリーンアップバージョンを投稿して、コミュニティを支援してください。
エリックアリク

コードをスーパーユーザーにしないでください。codereview.seに配置し、ここからリンクします。
ベンフォイト

@ user185282:良い点。私はその答えを否定しました。
忘れられない

親愛なるタオ:あなたは「このコードをどこで手に入れたか覚えていない」と書きました。このコードを書いたのですか、それとも誰かが書いたのですか?
忘れられない

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.