PowerShell మరియు WSL ఉపయోగించి Linux కమాండ్‌లను విండోస్‌లోకి సమగ్రపరచడం

విండోస్ డెవలపర్‌ల నుండి ఒక సాధారణ ప్రశ్న: “ఎందుకు ఇప్పటికీ లేదు <ВСТАВЬТЕ ТУТ ЛЮБИМУЮ КОМАНДУ LINUX>?. ఇది శక్తివంతమైన స్వైప్ అయినా less లేదా తెలిసిన సాధనాలు grep లేదా sed, Windows డెవలపర్‌లు తమ రోజువారీ పనిలో ఈ ఆదేశాలను సులభంగా యాక్సెస్ చేయాలనుకుంటున్నారు.

Linux కోసం Windows సబ్‌సిస్టమ్ (WSL) ఈ విషయంలో భారీ ముందడుగు వేసింది. Windows నుండి Linux ఆదేశాలను ప్రాక్సీ చేయడం ద్వారా కాల్ చేయడానికి ఇది మిమ్మల్ని అనుమతిస్తుంది wsl.exe (ఉదా, wsl ls) ఇది గణనీయమైన మెరుగుదల అయినప్పటికీ, ఈ ఎంపిక అనేక ప్రతికూలతలతో బాధపడుతోంది.

  • సర్వత్రా చేరిక wsl దుర్భరమైన మరియు అసహజమైన.
  • ఆర్గ్యుమెంట్‌లలో విండోస్ పాత్‌లు ఎల్లప్పుడూ పని చేయవు ఎందుకంటే బ్యాక్‌స్లాష్‌లు డైరెక్టరీ సెపరేటర్‌ల కంటే ఎస్కేప్ క్యారెక్టర్‌లుగా అన్వయించబడతాయి.
  • ఆర్గ్యుమెంట్‌లలో విండోస్ పాత్‌లు WSLలోని సంబంధిత మౌంట్ పాయింట్‌కి అనువదించబడవు.
  • మారుపేర్లు మరియు ఎన్విరాన్మెంట్ వేరియబుల్స్‌తో WSL ప్రొఫైల్‌లలో డిఫాల్ట్ సెట్టింగ్‌లు గౌరవించబడవు.
  • Linux పాత్ పూర్తికి మద్దతు లేదు.
  • కమాండ్ పూర్తికి మద్దతు లేదు.
  • వాదన పూర్తికి మద్దతు లేదు.

ఫలితంగా, Linux కమాండ్‌లు Windows క్రింద రెండవ-తరగతి పౌరుల వలె పరిగణించబడతాయి మరియు స్థానిక ఆదేశాల కంటే ఉపయోగించడం చాలా కష్టం. వారి హక్కులను సమం చేయడానికి, జాబితా చేయబడిన సమస్యలను పరిష్కరించడం అవసరం.

పవర్‌షెల్ ఫంక్షన్ రేపర్‌లు

పవర్‌షెల్ ఫంక్షన్ రేపర్‌లతో, మేము కమాండ్ కంప్లీషన్‌ని జోడించవచ్చు మరియు ప్రిఫిక్స్‌ల అవసరాన్ని తొలగించవచ్చు wsl, Windows పాత్‌లను WSL పాత్‌లుగా అనువదించడం. షెల్స్ కోసం ప్రాథమిక అవసరాలు:

  • ప్రతి Linux కమాండ్‌కు ఒకే పేరుతో ఒక ఫంక్షన్ రేపర్ ఉండాలి.
  • షెల్ తప్పనిసరిగా విండోస్ పాత్‌లను ఆర్గ్యుమెంట్‌లుగా గుర్తించి వాటిని WSL పాత్‌లుగా మార్చాలి.
  • షెల్ కాల్ చేయాలి wsl ఏదైనా పైప్‌లైన్ ఇన్‌పుట్‌కు తగిన Linux కమాండ్‌తో మరియు ఫంక్షన్‌కు పంపబడిన ఏదైనా కమాండ్ లైన్ ఆర్గ్యుమెంట్‌లను పాస్ చేయండి.

ఈ నమూనాను ఏదైనా కమాండ్‌కి వర్తింపజేయవచ్చు కాబట్టి, మేము ఈ రేపర్‌ల నిర్వచనాన్ని సంగ్రహించవచ్చు మరియు వాటిని దిగుమతి చేయడానికి ఆదేశాల జాబితా నుండి డైనమిక్‌గా రూపొందించవచ్చు.

# The commands to import.
$commands = "awk", "emacs", "grep", "head", "less", "ls", "man", "sed", "seq", "ssh", "tail", "vim"
 
# Register a function for each command.
$commands | ForEach-Object { Invoke-Expression @"
Remove-Alias $_ -Force -ErrorAction Ignore
function global:$_() {
    for (`$i = 0; `$i -lt `$args.Count; `$i++) {
        # If a path is absolute with a qualifier (e.g. C:), run it through wslpath to map it to the appropriate mount point.
        if (Split-Path `$args[`$i] -IsAbsolute -ErrorAction Ignore) {
            `$args[`$i] = Format-WslArgument (wsl.exe wslpath (`$args[`$i] -replace "", "/"))
        # If a path is relative, the current working directory will be translated to an appropriate mount point, so just format it.
        } elseif (Test-Path `$args[`$i] -ErrorAction Ignore) {
            `$args[`$i] = Format-WslArgument (`$args[`$i] -replace "", "/")
        }
    }
 
    if (`$input.MoveNext()) {
        `$input.Reset()
        `$input | wsl.exe $_ (`$args -split ' ')
    } else {
        wsl.exe $_ (`$args -split ' ')
    }
}
"@
}

జాబితా $command దిగుమతి ఆదేశాలను నిర్వచిస్తుంది. మేము కమాండ్‌ని ఉపయోగించి వాటిలో ప్రతిదానికి ఒక ఫంక్షన్ రేపర్‌ను డైనమిక్‌గా ఉత్పత్తి చేస్తాము Invoke-Expression (ఫంక్షన్‌తో విభేదించే ఏదైనా మారుపేర్లను మొదట తొలగించడం ద్వారా).

ఫంక్షన్ కమాండ్ లైన్ ఆర్గ్యుమెంట్‌ల ద్వారా పునరావృతమవుతుంది, ఆదేశాలను ఉపయోగించి విండోస్ పాత్‌లను నిర్ణయిస్తుంది Split-Path и Test-Pathఆపై ఈ మార్గాలను WSL పాత్‌లుగా మారుస్తుంది. మేము సహాయక ఫంక్షన్ ద్వారా మార్గాలను అమలు చేస్తాము Format-WslArgument, మేము తరువాత నిర్వచించాము. ఇది ఖాళీలు మరియు కుండలీకరణాలు వంటి ప్రత్యేక అక్షరాలను తప్పించుకుంటుంది, లేకపోతే తప్పుగా అర్థం చేసుకోవచ్చు.

చివరగా, మేము తెలియజేస్తాము wsl పైప్‌లైన్ ఇన్‌పుట్ మరియు ఏదైనా కమాండ్ లైన్ ఆర్గ్యుమెంట్‌లు.

ఈ రేపర్‌లతో మీరు మీ ఇష్టమైన Linux ఆదేశాలను ఉపసర్గను జోడించకుండా మరింత సహజమైన రీతిలో కాల్ చేయవచ్చు wsl మరియు మార్గాలు ఎలా మార్చబడతాయి అనే దాని గురించి చింతించకుండా:

  • man bash
  • less -i $profile.CurrentUserAllHosts
  • ls -Al C:Windows | less
  • grep -Ein error *.log
  • tail -f *.log

కమాండ్‌ల యొక్క ప్రాథమిక సెట్ ఇక్కడ చూపబడింది, అయితే మీరు జాబితాకు జోడించడం ద్వారా ఏదైనా Linux కమాండ్ కోసం షెల్‌ను సృష్టించవచ్చు. మీరు ఈ కోడ్‌ని మీకు జోడిస్తే ప్రొఫైల్ PowerShell, ఈ ఆదేశాలు స్థానిక ఆదేశాల వలె ప్రతి PowerShell సెషన్‌లో మీకు అందుబాటులో ఉంటాయి!

డిఫాల్ట్ సెట్టింగ్‌లు

Linuxలో, లాగిన్ ప్రొఫైల్‌లలో మారుపేర్లు మరియు/లేదా ఎన్విరాన్‌మెంట్ వేరియబుల్‌లను నిర్వచించడం సర్వసాధారణం, తరచుగా ఉపయోగించే ఆదేశాల కోసం డిఫాల్ట్ పారామితులను సెట్ చేయడం (ఉదాహరణకు, alias ls=ls -AFh లేదా export LESS=-i) నాన్-ఇంటరాక్టివ్ షెల్ ద్వారా ప్రాక్సీ చేయడం వల్ల కలిగే నష్టాలలో ఒకటి wsl.exe - ప్రొఫైల్‌లు లోడ్ చేయబడలేదు, కాబట్టి ఈ ఎంపికలు డిఫాల్ట్‌గా అందుబాటులో ఉండవు (అంటే. ls WSL లో మరియు wsl ls పైన నిర్వచించిన మారుపేరుతో విభిన్నంగా ప్రవర్తిస్తుంది).

PowerShell అందిస్తుంది $PSDefaultParameterValues, డిఫాల్ట్ పారామితులను నిర్వచించడానికి ప్రామాణిక మెకానిజం, కానీ cmdlets మరియు అధునాతన ఫంక్షన్లకు మాత్రమే. వాస్తవానికి, మేము మా షెల్‌ల నుండి అధునాతన ఫంక్షన్‌లను చేయవచ్చు, కానీ ఇది అనవసరమైన సంక్లిష్టతలను పరిచయం చేస్తుంది (ఉదాహరణకు, PowerShell పాక్షిక పారామితి పేర్లను సహసంబంధం చేస్తుంది (ఉదాహరణకు, -a తో సహసంబంధం -ArgumentList), ఇది పాక్షిక పేర్లను ఆర్గ్యుమెంట్‌లుగా తీసుకునే Linux ఆదేశాలతో విభేదిస్తుంది), మరియు డిఫాల్ట్ విలువలను నిర్వచించే వాక్యనిర్మాణం అత్యంత సముచితమైనది కాదు (డిఫాల్ట్ ఆర్గ్యుమెంట్‌లకు కీలోని పారామీటర్ పేరు అవసరం, కమాండ్ పేరు మాత్రమే కాదు) .

అయితే, మా షెల్‌లకు స్వల్ప మార్పుతో, మేము ఇలాంటి నమూనాను అమలు చేయవచ్చు $PSDefaultParameterValues, మరియు Linux ఆదేశాల కోసం డిఫాల్ట్ ఎంపికలను ప్రారంభించండి!

function global:$_() {
    …
 
    `$defaultArgs = ((`$WslDefaultParameterValues.$_ -split ' '), "")[`$WslDefaultParameterValues.Disabled -eq `$true]
    if (`$input.MoveNext()) {
        `$input.Reset()
        `$input | wsl.exe $_ `$defaultArgs (`$args -split ' ')
    } else {
        wsl.exe $_ `$defaultArgs (`$args -split ' ')
    }
}

ఉత్తీర్ణత $WslDefaultParameterValues కమాండ్ లైన్‌కు, మేము పారామితులను ద్వారా పంపుతాము wsl.exe. డిఫాల్ట్ సెట్టింగ్‌లను కాన్ఫిగర్ చేయడానికి మీ PowerShell ప్రొఫైల్‌కు సూచనలను ఎలా జోడించాలో క్రింది చూపిస్తుంది. ఇప్పుడు మనం చేయగలము!

$WslDefaultParameterValues["grep"] = "-E"
$WslDefaultParameterValues["less"] = "-i"
$WslDefaultParameterValues["ls"] = "-AFh --group-directories-first"

పారామితులు మోడల్ చేయబడినందున $PSDefaultParameterValues, నువ్వు చేయగలవు వాటిని నిలిపివేయడం సులభం కీని ఇన్‌స్టాల్ చేయడం ద్వారా తాత్కాలికంగా "Disabled" అర్థం లోకి $true. ప్రత్యేక హాష్ పట్టిక యొక్క అదనపు ప్రయోజనం డిసేబుల్ సామర్ధ్యం $WslDefaultParameterValues నుండి విడిగా $PSDefaultParameterValues.

వాదన పూర్తి

కమాండ్ ఉపయోగించి ఆర్గ్యుమెంట్ ట్రైలర్‌లను నమోదు చేయడానికి PowerShell మిమ్మల్ని అనుమతిస్తుంది Register-ArgumentCompleter. బాష్ శక్తివంతమైనది ప్రోగ్రామబుల్ స్వీయ-పూర్తి సాధనాలు. WSL పవర్‌షెల్ నుండి బాష్‌కి కాల్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది. మేము మా పవర్‌షెల్ ఫంక్షన్ రేపర్‌ల కోసం ఆర్గ్యుమెంట్ కంప్లీషన్‌లను నమోదు చేయగలిగితే మరియు కంప్లీషన్‌లను రూపొందించడానికి బాష్‌కి కాల్ చేయగలిగితే, మేము బాష్ వలె అదే ఖచ్చితత్వంతో పూర్తి వాదనను పూర్తి చేస్తాము!

# Register an ArgumentCompleter that shims bash's programmable completion.
Register-ArgumentCompleter -CommandName $commands -ScriptBlock {
    param($wordToComplete, $commandAst, $cursorPosition)
 
    # Map the command to the appropriate bash completion function.
    $F = switch ($commandAst.CommandElements[0].Value) {
        {$_ -in "awk", "grep", "head", "less", "ls", "sed", "seq", "tail"} {
            "_longopt"
            break
        }
 
        "man" {
            "_man"
            break
        }
 
        "ssh" {
            "_ssh"
            break
        }
 
        Default {
            "_minimal"
            break
        }
    }
 
    # Populate bash programmable completion variables.
    $COMP_LINE = "`"$commandAst`""
    $COMP_WORDS = "('$($commandAst.CommandElements.Extent.Text -join "' '")')" -replace "''", "'"
    for ($i = 1; $i -lt $commandAst.CommandElements.Count; $i++) {
        $extent = $commandAst.CommandElements[$i].Extent
        if ($cursorPosition -lt $extent.EndColumnNumber) {
            # The cursor is in the middle of a word to complete.
            $previousWord = $commandAst.CommandElements[$i - 1].Extent.Text
            $COMP_CWORD = $i
            break
        } elseif ($cursorPosition -eq $extent.EndColumnNumber) {
            # The cursor is immediately after the current word.
            $previousWord = $extent.Text
            $COMP_CWORD = $i + 1
            break
        } elseif ($cursorPosition -lt $extent.StartColumnNumber) {
            # The cursor is within whitespace between the previous and current words.
            $previousWord = $commandAst.CommandElements[$i - 1].Extent.Text
            $COMP_CWORD = $i
            break
        } elseif ($i -eq $commandAst.CommandElements.Count - 1 -and $cursorPosition -gt $extent.EndColumnNumber) {
            # The cursor is within whitespace at the end of the line.
            $previousWord = $extent.Text
            $COMP_CWORD = $i + 1
            break
        }
    }
 
    # Repopulate bash programmable completion variables for scenarios like '/mnt/c/Program Files'/<TAB> where <TAB> should continue completing the quoted path.
    $currentExtent = $commandAst.CommandElements[$COMP_CWORD].Extent
    $previousExtent = $commandAst.CommandElements[$COMP_CWORD - 1].Extent
    if ($currentExtent.Text -like "/*" -and $currentExtent.StartColumnNumber -eq $previousExtent.EndColumnNumber) {
        $COMP_LINE = $COMP_LINE -replace "$($previousExtent.Text)$($currentExtent.Text)", $wordToComplete
        $COMP_WORDS = $COMP_WORDS -replace "$($previousExtent.Text) '$($currentExtent.Text)'", $wordToComplete
        $previousWord = $commandAst.CommandElements[$COMP_CWORD - 2].Extent.Text
        $COMP_CWORD -= 1
    }
 
    # Build the command to pass to WSL.
    $command = $commandAst.CommandElements[0].Value
    $bashCompletion = ". /usr/share/bash-completion/bash_completion 2> /dev/null"
    $commandCompletion = ". /usr/share/bash-completion/completions/$command 2> /dev/null"
    $COMPINPUT = "COMP_LINE=$COMP_LINE; COMP_WORDS=$COMP_WORDS; COMP_CWORD=$COMP_CWORD; COMP_POINT=$cursorPosition"
    $COMPGEN = "bind `"set completion-ignore-case on`" 2> /dev/null; $F `"$command`" `"$wordToComplete`" `"$previousWord`" 2> /dev/null"
    $COMPREPLY = "IFS=`$'n'; echo `"`${COMPREPLY[*]}`""
    $commandLine = "$bashCompletion; $commandCompletion; $COMPINPUT; $COMPGEN; $COMPREPLY" -split ' '
 
    # Invoke bash completion and return CompletionResults.
    $previousCompletionText = ""
    (wsl.exe $commandLine) -split 'n' |
    Sort-Object -Unique -CaseSensitive |
    ForEach-Object {
        if ($wordToComplete -match "(.*=).*") {
            $completionText = Format-WslArgument ($Matches[1] + $_) $true
            $listItemText = $_
        } else {
            $completionText = Format-WslArgument $_ $true
            $listItemText = $completionText
        }
 
        if ($completionText -eq $previousCompletionText) {
            # Differentiate completions that differ only by case otherwise PowerShell will view them as duplicate.
            $listItemText += ' '
        }
 
        $previousCompletionText = $completionText
        [System.Management.Automation.CompletionResult]::new($completionText, $listItemText, 'ParameterName', $completionText)
    }
}
 
# Helper function to escape characters in arguments passed to WSL that would otherwise be misinterpreted.
function global:Format-WslArgument([string]$arg, [bool]$interactive) {
    if ($interactive -and $arg.Contains(" ")) {
        return "'$arg'"
    } else {
        return ($arg -replace " ", " ") -replace "([()|])", ('$1', '`$1')[$interactive]
    }
}

బాష్ యొక్క కొన్ని అంతర్గత విధులను అర్థం చేసుకోకుండా కోడ్ కొంచెం దట్టంగా ఉంటుంది, కానీ ప్రాథమికంగా మనం చేసేది ఇది:

  • జాబితాను పాస్ చేయడం ద్వారా మా అన్ని ఫంక్షన్ రేపర్‌ల కోసం ఆర్గ్యుమెంట్ కంప్లీటర్‌ను నమోదు చేయడం $commands పరామితిలో -CommandName కోసం Register-ArgumentCompleter.
  • మేము ప్రతి ఆదేశాన్ని స్వయంపూర్తి కోసం ఉపయోగించే షెల్ ఫంక్షన్‌కు మ్యాప్ చేస్తాము (స్వయంపూర్తి స్పెసిఫికేషన్‌లను నిర్వచించడానికి, బాష్ ఉపయోగాలు $F, సంక్షిప్తీకరణ complete -F <FUNCTION>).
  • పవర్‌షెల్ ఆర్గ్యుమెంట్‌లను మారుస్తోంది $wordToComplete, $commandAst и $cursorPosition స్పెసిఫికేషన్‌ల ప్రకారం బాష్ స్వయంపూర్తి ఫంక్షన్‌ల ద్వారా ఆశించిన ఆకృతిలోకి ప్రోగ్రామబుల్ స్వీయ-పూర్తి బాష్.
  • మేము బదిలీ చేయడానికి కమాండ్ లైన్ కంపోజ్ చేస్తాము wsl.exe, ఇది పర్యావరణం సరిగ్గా సెటప్ చేయబడిందని నిర్ధారిస్తుంది, తగిన స్వీయ-పూర్తి ఫంక్షన్‌ని పిలుస్తుంది మరియు ఫలితాలను లైన్-బై-లైన్ పద్ధతిలో అవుట్‌పుట్ చేస్తుంది.
  • అప్పుడు మేము పిలుస్తాము wsl కమాండ్ లైన్‌తో, మేము అవుట్‌పుట్‌ను లైన్ సెపరేటర్‌ల ద్వారా వేరు చేస్తాము మరియు ప్రతిదానికీ ఉత్పత్తి చేస్తాము CompletionResults, వాటిని క్రమబద్ధీకరించడం మరియు తప్పుగా అన్వయించబడే ఖాళీలు మరియు కుండలీకరణాలు వంటి అక్షరాలు తప్పించుకోవడం.

ఫలితంగా, మా Linux కమాండ్ షెల్‌లు సరిగ్గా అదే స్వయంపూర్తి బాష్‌ని ఉపయోగిస్తాయి! ఉదాహరణకి:

  • ssh -c <TAB> -J <TAB> -m <TAB> -O <TAB> -o <TAB> -Q <TAB> -w <TAB> -b <TAB>

ప్రతి స్వయంపూర్తి మునుపటి వాదనకు నిర్దిష్ట విలువలను అందిస్తుంది, WSL నుండి తెలిసిన హోస్ట్‌ల వంటి కాన్ఫిగరేషన్ డేటాను చదవడం!

<TAB> పారామితుల ద్వారా సైకిల్ చేస్తుంది. <Ctrl + пробел> అందుబాటులో ఉన్న అన్ని ఎంపికలను చూపుతుంది.

అదనంగా, మేము ఇప్పుడు బాష్ స్వయంపూర్తిని కలిగి ఉన్నందున, మీరు పవర్‌షెల్‌లో నేరుగా Linux పాత్‌లను స్వీయపూర్తి చేయవచ్చు!

  • less /etc/<TAB>
  • ls /usr/share/<TAB>
  • vim ~/.bash<TAB>

బాష్ స్వయంపూర్తి ఎటువంటి ఫలితాలను ఇవ్వని సందర్భాల్లో, పవర్‌షెల్ సిస్టమ్ డిఫాల్ట్ విండోస్ పాత్‌లకు తిరిగి వస్తుంది. అందువలన, ఆచరణలో, మీరు మీ అభీష్టానుసారం రెండు మార్గాలను ఏకకాలంలో ఉపయోగించవచ్చు.

తీర్మానం

PowerShell మరియు WSLని ఉపయోగించి, మేము Linux ఆదేశాలను స్థానిక అప్లికేషన్‌లుగా Windows లోకి ఇంటిగ్రేట్ చేయవచ్చు. Win32 బిల్డ్‌లు లేదా Linux యుటిలిటీల కోసం శోధించాల్సిన అవసరం లేదు లేదా Linux షెల్‌కి వెళ్లడం ద్వారా మీ వర్క్‌ఫ్లోకు అంతరాయం కలిగించాల్సిన అవసరం లేదు. కేవలం WSLని ఇన్‌స్టాల్ చేయండి, కాన్ఫిగర్ చేయండి పవర్‌షెల్ ప్రొఫైల్ и మీరు దిగుమతి చేయాలనుకుంటున్న ఆదేశాలను జాబితా చేయండి! Linux మరియు Windows కమాండ్ పారామీటర్‌లు మరియు ఫైల్ పాత్‌ల కోసం రిచ్ ఆటోకంప్లీషన్ అనేది నేటి స్థానిక Windows కమాండ్‌లలో కూడా అందుబాటులో లేని కార్యాచరణ.

పైన వివరించిన పూర్తి సోర్స్ కోడ్, అలాగే మీ వర్క్‌ఫ్లోలో చేర్చడానికి అదనపు మార్గదర్శకాలు అందుబాటులో ఉన్నాయి ఇక్కడ.

మీకు ఏ Linux కమాండ్‌లు చాలా ఉపయోగకరంగా ఉన్నాయి? Windowsలో పని చేస్తున్నప్పుడు ఏ ఇతర సాధారణ విషయాలు లేవు? వ్యాఖ్యలలో వ్రాయండి లేదా GitHubలో!

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి