Haɗa umarnin Linux cikin Windows ta amfani da PowerShell da WSL

Tambaya ta yau da kullun daga masu haɓaka Windows: “Me yasa har yanzu babu <ВСТАВЬТЕ ТУТ ЛЮБИМУЮ КОМАНДУ LINUX>? Ko yana da ƙarfi swipe less ko kayan aikin da aka sani grep ko sed, Masu haɓaka Windows suna son samun sauƙi ga waɗannan umarni a cikin aikinsu na yau da kullun.

Tsarin Windows don Linux (WSL) ya kawo babban ci gaba a wannan fanni. Yana ba ku damar kiran umarnin Linux daga Windows ta hanyar ba da izini ta hanyar wsl.exe (misali. wsl ls). Kodayake wannan babban ci gaba ne, wannan zaɓin yana fama da rashin amfani da yawa.

  • Bugu da kari wsl m da m.
  • Hanyoyin Windows a cikin gardama ba koyaushe suke aiki ba saboda ana fassara ja da baya azaman haruffan tserewa maimakon masu raba kundin adireshi.
  • Ba a fassara hanyoyin Windows a cikin gardama zuwa madaidaicin wurin tudu a WSL.
  • Ba a mutunta saitunan tsoho a cikin bayanan martaba na WSL tare da laƙabi da masu canjin yanayi.
  • Ba a tallafawa kammala hanyar Linux.
  • Ba a tallafawa kammala umarni.
  • Ba a goyan bayan kammala jayayya.

Sakamakon haka, ana ɗaukar umarnin Linux kamar ƴan ƙasa na biyu a ƙarƙashin Windows-kuma sun fi wuya a yi amfani da su fiye da dokokin ƙasa. Don daidaita haƙƙin su, wajibi ne a magance matsalolin da aka lissafa.

Kayan aikin PowerShell

Tare da kayan aikin PowerShell, za mu iya ƙara cika umarni da kawar da buƙatar prefixes wsl, fassara hanyoyin Windows zuwa hanyoyin WSL. Abubuwan buƙatu na asali don harsashi:

  • Ga kowane umarnin Linux dole ne a sami abin rufe aiki guda ɗaya mai suna iri ɗaya.
  • Dole ne harsashi ya gane hanyoyin Windows da suka wuce azaman mahawara kuma ya canza su zuwa hanyoyin WSL.
  • Ya kamata harsashi ya kira wsl tare da umarnin Linux da ya dace zuwa kowane shigarwar bututun kuma wuce kowane gardamar layin umarni da aka wuce zuwa aikin.

Tun da ana iya amfani da wannan ƙirar ga kowane umarni, za mu iya taƙaita ma'anar waɗannan kundi sannan mu samar da su cikin kuzari daga jerin umarni don shigo da su.

# 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 ' ')
    }
}
"@
}

jerin $command yana bayyana umarnin shigo da kaya. Sa'an nan kuma mu ƙirƙira da ƙarfi da ƙarfi ga kowane ɗayansu ta amfani da umarnin Invoke-Expression (ta hanyar cire duk wani laƙabi da zai ci karo da aikin).

Ayyukan yana jujjuyawa akan gardamar layin umarni, yana ƙayyade hanyoyin Windows ta amfani da umarni Split-Path и Test-Pathsannan ya juya waɗannan hanyoyin zuwa hanyoyin WSL. Muna tafiyar da hanyoyi ta hanyar aikin taimako Format-WslArgument, wanda za mu ayyana nan gaba. Yana tserewa haruffa na musamman kamar sarari da baƙaƙe waɗanda ba za a yi musu mummunar fassara ba.

A ƙarshe, muna isarwa wsl shigar da bututun da kowane gardama layin umarni.

Tare da waɗannan nannade zaka iya kiran umarnin Linux da kuka fi so ta hanya mafi kyau ba tare da ƙara prefix ba wsl kuma ba tare da damuwa da yadda ake juya hanyoyin ba:

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

Ana nuna ainihin saitin umarni anan, amma zaku iya ƙirƙirar harsashi don kowane umarnin Linux ta hanyar ƙara shi cikin jerin kawai. Idan kun ƙara wannan lambar zuwa naku bayanin martaba PowerShell, waɗannan umarni za su kasance a gare ku a kowane zaman PowerShell, kamar umarnin ƙasa!

Saitunan Tsohuwar

A cikin Linux, ya zama ruwan dare don ayyana laƙabi da/ko masu canjin yanayi a cikin bayanan shiga, saita sigogin tsoho don umarnin da ake amfani da su akai-akai (misali, alias ls=ls -AFh ko export LESS=-i). Ɗaya daga cikin rashin amfani da wakili ta hanyar harsashi mara hulɗa wsl.exe - cewa bayanan martaba ba a ɗora su ba, don haka waɗannan zaɓuɓɓukan ba su samuwa ta hanyar tsoho (watau. ls a cikin WSL da wsl ls za su yi daban-daban tare da laƙabin da aka ayyana a sama).

PowerShell yana bayarwa $PSDefaultParameterValues, daidaitaccen tsari don ayyana sigogin tsoho, amma don cmdlets kawai da ayyukan ci-gaba. Tabbas, zamu iya yin ayyuka na ci gaba daga cikin harsashi, amma wannan yana gabatar da matsalolin da ba dole ba (misali, PowerShell yana daidaita sunaye na yanki (misali, -a yayi daidai da -ArgumentList), wanda zai ci karo da umarnin Linux wanda ke ɗaukar sunaye na yanki azaman gardama), kuma ma'anar ma'anar ma'auni na tsoho ba zai zama mafi dacewa ba (maganganun tsoho suna buƙatar sunan siga a cikin maɓalli, ba kawai sunan umarni ba) .

Koyaya, tare da ɗan gyare-gyare ga harsashi, za mu iya aiwatar da samfurin kama $PSDefaultParameterValues, kuma ba da damar zaɓuɓɓukan tsoho don umarnin 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 ' ')
    }
}

Wucewa $WslDefaultParameterValues zuwa layin umarni, muna aika sigogi ta hanyar wsl.exe. Mai zuwa yana nuna yadda ake ƙara umarni zuwa bayanin martaba na PowerShell don saita saitunan tsoho. Yanzu za mu iya yi!

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

Tun da sigogin ana yin su ne bayan $PSDefaultParameterValueszaka iya yana da sauƙi a kashe su na dan lokaci ta hanyar shigar da maɓallin "Disabled" cikin ma'ana $true. Ƙarin fa'idar tebur ɗin zanta daban shine ikon kashewa $WslDefaultParameterValues daban daga $PSDefaultParameterValues.

Ƙarshen jayayya

PowerShell yana ba ku damar yin rijistar tireloli masu hujja ta amfani da umarnin Register-ArgumentCompleter. Bash yana da ƙarfi shirye-shirye na atomatik kammala kayan aikin. WSL yana ba ku damar kiran bash daga PowerShell. Idan za mu iya yin rajistar kammala gardama don kayan aikin mu na PowerShell kuma mu kira bash don samar da abubuwan da aka kammala, muna samun cikakkiyar hujja tare da daidaici ɗaya kamar bash kanta!

# 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]
    }
}

Lambar tana da ɗan girma ba tare da fahimtar wasu ayyukan ciki na bash ba, amma ainihin abin da muke yi shine:

  • Rijista mai cikar gardama ga duk nade-naden ayyukan mu ta hanyar wuce lissafi $commands a cikin siga -CommandName to Register-ArgumentCompleter.
  • Muna yin taswirar kowane umarni zuwa aikin harsashi wanda bash ke amfani da shi don cikawa ta atomatik (don ayyana ƙayyadaddun ƙayyadaddun ƙayyadaddun atomatik, amfani da bash $F, gajarta don complete -F <FUNCTION>).
  • Mayar da Hujja ta PowerShell $wordToComplete, $commandAst и $cursorPosition cikin tsarin da ake tsammani ta ayyukan bash's kammalawa ta atomatik bisa ga ƙayyadaddun bayanai shirye-shirye auto-kammala bash.
  • Muna tsara layin umarni don canjawa zuwa wsl.exe, wanda ke tabbatar da cewa an saita yanayin daidai, yana kiran aikin da ya dace ta atomatik, kuma yana fitar da sakamakon a cikin layi-by-line fashion.
  • Sai mu kira wsl tare da layin umarni, muna raba fitarwa ta hanyar masu rarraba layi kuma muna samar da kowane CompletionResults, rarrabuwar su da gujewa haruffa kamar sarari da baƙaƙe waɗanda ba za a yi musu mummunar fassara ba.

Sakamakon haka, bawoyi na Linux ɗinmu za su yi amfani da daidaitaccen aikin atomatik kamar bash! Misali:

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

Kowane kammalawa ta atomatik yana ba da ƙima ta musamman ga gardamar da ta gabata, karanta bayanan sanyi kamar sanannun runduna daga WSL!

<TAB> za a sake zagayowar ta cikin sigogi. <Ctrl + пробел> zai nuna duk zaɓuɓɓukan da ake da su.

Plusari, tunda yanzu muna da bash autocompletion, zaku iya cika hanyoyin Linux kai tsaye a cikin PowerShell!

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

A lokuta inda bash autocompletion ba ya samar da wani sakamako, PowerShell ya koma tsarin tsoho hanyoyin Windows. Don haka, a aikace, zaku iya amfani da hanyoyi biyu a lokaci guda bisa ga ra'ayinku.

ƙarshe

Amfani da PowerShell da WSL, zamu iya haɗa umarnin Linux cikin Windows azaman aikace-aikacen asali. Babu buƙatar bincika ginin Win32 ko abubuwan amfani na Linux ko katse aikin ku ta hanyar zuwa harsashi na Linux. Kawai shigar da WSL, daidaita Bayanan martaba na PowerShell и jera umarnin da kuke son shigo da su! Ƙarfafa kai-da-kai don Linux da sigogin umarni na Windows da hanyoyin fayil ayyuka ne waɗanda ba ma samuwa a cikin umarnin Windows na asali a yau.

Cikakkun lambar tushe da aka bayyana a sama, da ƙarin jagorori don haɗa ta cikin tafiyar aikinku, akwai a nan.

Wadanne umarni Linux kuka fi amfani dasu? Wadanne abubuwa gama gari ne suka ɓace yayin aiki a cikin Windows? Rubuta a cikin sharhi ko ku GitHub!

source: www.habr.com

Add a comment