Ag amalachadh òrdughan Linux a-steach do Windows a’ cleachdadh PowerShell agus WSL

Ceist àbhaisteach bho luchd-leasachaidh Windows: “Carson nach eil <ВСТАВЬТЕ ТУТ ЛЮБИМУЮ КОМАНДУ LINUX>?. Ge bith an e swipe cumhachdach a th’ ann less no innealan eòlach grep no sed, Tha luchd-leasachaidh Windows ag iarraidh ruigsinneachd furasta air na h-òrdughan sin nan obair làitheil.

Fo-shiostam Windows airson Linux (WSL) air ceum mòr air adhart a dhèanamh a thaobh seo. Leigidh e leat òrdughan Linux a ghairm bho Windows le bhith gan proxy troimhe wsl.exe (mar eisimpleir, wsl ls). Ged a tha seo na leasachadh mòr, tha an roghainn seo a 'fulang le grunn eas-bhuannachdan.

  • Cur-ris uile-làthaireach wsl sgìth agus mì-nàdarrach.
  • Chan eil slighean Windows ann an argamaidean an-còmhnaidh ag obair oir tha cnapan-starra air am mìneachadh mar charactaran teiche seach luchd-sgaraidh eòlaire.
  • Chan eil slighean Windows ann an argamaidean air an eadar-theangachadh chun a’ phuing sreap co-fhreagarrach ann an WSL.
  • Chan eilear a’ toirt spèis do shuidheachaidhean bunaiteach ann am pròifilean WSL le ailias agus caochladairean àrainneachd.
  • Chan eil taic ri crìoch a chur air slighe Linux.
  • Chan eil taic ri crìochnachadh àithne.
  • Chan eil taic ri crìoch na h-argamaid.

Mar thoradh air an sin, thathas a’ làimhseachadh òrdughan Linux mar shaoranaich den dàrna ìre fo Windows - agus tha iad nas duilghe an cleachdadh na òrdughan dùthchasach. Gus na còraichean aca a cho-ionannachd, feumar na duilgheadasan clàraichte fhuasgladh.

Còmhdaichean gnìomh PowerShell

Le pasgain gnìomh PowerShell, is urrainn dhuinn crìochnachadh àithne a chuir ris agus cuir às don fheum air ro-leasachain wsl, ag eadar-theangachadh slighean Windows gu slighean WSL. Riatanasan bunaiteach airson sligean:

  • Airson gach àithne Linux feumaidh aon inneal-còmhdaich gnìomh a bhith ann leis an aon ainm.
  • Feumaidh an t-slige aithneachadh na slighean Windows a chaidh seachad mar argamaidean agus an tionndadh gu slighean WSL.
  • Bu chòir don t-slige glaodh wsl leis an àithne Linux iomchaidh gu cuir a-steach loidhne-phìoban sam bith agus a’ dol seachad air argamaidean loidhne-àithne sam bith a thèid a thoirt don ghnìomh.

Leis gum faodar am pàtran seo a chuir an sàs ann an àithne sam bith, is urrainn dhuinn mìneachadh nan pasgain sin a thoirt a-mach agus an gineadh gu dinamach bho liosta òrdughan airson an toirt a-steach.

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

Liosta de $command a’ mìneachadh òrdughan in-mhalairt. Bidh sinn an uairsin a’ gineadh inneal fillte gnìomh airson gach fear dhiubh a’ cleachdadh an àithne Invoke-Expression (le bhith a’ toirt air falbh ailias sam bith a bhiodh an aghaidh a’ ghnìomh an-toiseach).

Bidh an gnìomh ag ath-aithris thairis air argamaidean loidhne-àithne, a’ dearbhadh slighean Windows a’ cleachdadh òrdughan Split-Path и Test-Pathagus an uairsin tionndaidh na slighean sin gu slighean WSL. Bidh sinn a’ ruith nan slighean tro ghnìomh cuideachaidh Format-WslArgument, a mhìnicheas sinn nas fhaide air adhart. Bidh e a’ teicheadh ​​​​bho charactaran sònraichte leithid beàrnan agus bragan a bhiodh air an mì-mhìneachadh air dhòigh eile.

Mu dheireadh, tha sinn a 'toirt seachad wsl cuir a-steach loidhne-phìoban agus argamaidean loidhne-àithne sam bith.

Leis na pasgain sin faodaidh tu na h-òrdughan Linux as fheàrr leat a ghairm ann an dòigh nas nàdarraiche gun ro-leasachan a chuir ris wsl agus gun amharus a bhi air mar a ta na slighean air an iompachadh :

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

Tha an seata òrdughan bunaiteach ri fhaicinn an seo, ach faodaidh tu slige a chruthachadh airson àithne Linux sam bith le bhith dìreach ga chur ris an liosta. Ma chuireas tu an còd seo ris a’ chòd agad phròifil PowerShell, bidh na h-òrdughan sin rim faighinn dhut anns a h-uile seisean PowerShell, dìreach mar òrdughan dùthchasach!

Roghainnean bunaiteach

Ann an Linux, tha e cumanta aliases agus / no caochladairean àrainneachd a mhìneachadh ann am pròifilean logadh a-steach, a’ suidheachadh paramadairean bunaiteach airson òrdughan a chleachdar gu tric (mar eisimpleir, alias ls=ls -AFh no export LESS=-i). Is e aon de na h-eas-bhuannachdan a tha ann a bhith a’ proxying tro shligean neo-eadar-ghnìomhach wsl.exe - nach eil na pròifilean air an luchdachadh, agus mar sin chan eil na roghainnean sin rim faighinn gu bunaiteach (i.e. ls ann an WSL agus wsl ls giùlan fhèin ann an dòigh eadar-dhealaichte leis an alias a tha air a mhìneachadh gu h-àrd).

Tha PowerShell a’ toirt seachad $PSDefault ParameterLuachan, inneal àbhaisteach airson crìochan bunaiteach a mhìneachadh, ach dìreach airson cmdlets agus gnìomhan adhartach. Gu dearbh, is urrainn dhuinn gnìomhan adhartach a dhèanamh a-mach às na sligean againn, ach tha seo a ’toirt a-steach duilgheadasan neo-riatanach (mar eisimpleir, tha PowerShell a’ ceangal ainmean paramadair pàirt (mar eisimpleir, -a co-cheangailte ri -ArgumentList).

Ach, le atharrachadh beag air na sligean againn, is urrainn dhuinn modail coltach ris a chuir an gnìomh $PSDefaultParameterValues, agus cuir an comas roghainnean bunaiteach airson òrdughan 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 ' ')
    }
}

A' dol seachad $WslDefaultParameterValues chun loidhne-àithne, cuiridh sinn paramadairean tro wsl.exe. Tha na leanas a’ sealltainn mar a chuireas tu stiùireadh ris a’ phròifil PowerShell agad gus na roghainnean bunaiteach a rèiteachadh. A-nis is urrainn dhuinn a dhèanamh!

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

Leis gu bheil na paramadairean air an dealbhadh às deidh $PSDefaultParameterValuesfaodaidh tu tha e furasta an cur à comas gu sealach le bhith a’ stàladh na h-iuchrach "Disabled" ann an ciall $true. Is e buannachd a bharrachd de bhòrd hash air leth an comas a chuir dheth $WslDefaultParameterValues fa leth bho $PSDefaultParameterValues.

Argamaid a chrìochnachadh

Leigidh PowerShell leat luchd-tarraing argamaid a chlàradh a’ cleachdadh an àithne Register-ArgumentCompleter. Tha cumhachd cumhachdach aig Bash innealan fèin-chrìochnachaidh prògramaichte. Leigidh WSL leat bash a ghairm bho PowerShell. Mas urrainn dhuinn crìoch a chuir air argamaidean a chlàradh airson ar luchd-gleidhidh gnìomh PowerShell agus bash gairm gus na crìochnachaidhean a ghineadh, gheibh sinn làn argamaid crìochnachadh leis an aon chinnt ri bash fhèin!

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

Tha an còd beagan dùmhail gun a bhith a’ tuigsinn cuid de ghnìomhan a-staigh bash, ach gu bunaiteach is e na bhios sinn a’ dèanamh:

  • A’ clàradh neach-crìochnachaidh argamaid airson a h-uile pasgan gnìomh againn le bhith a’ dol seachad air liosta $commands ann am paramadair -CommandName airson Register-ArgumentCompleter.
  • Bidh sinn a’ mapadh gach àithne don ghnìomh shligean a bhios bash a’ cleachdadh airson fèin-choileanadh (gus mion-chomharrachadh fèin-choileanaidh a mhìneachadh, cleachdaidhean bash $F, giorrachadh airson complete -F <FUNCTION>).
  • Argamaidean PowerShell a thionndadh $wordToComplete, $commandAst и $cursorPosition a-steach don chruth ris a bheil dùil le gnìomhan fèin-chrìochnachaidh bash a rèir nan sònrachaidhean fèin-chrìochnachadh prògramaichte bash.
  • Bidh sinn a 'dèanamh loidhne-àithne airson gluasad gu wsl.exe, a nì cinnteach gu bheil an àrainneachd air a stèidheachadh gu ceart, a’ gairm an gnìomh fèin-chrìochnachaidh iomchaidh, agus a’ toirt a-mach na toraidhean ann am fasan loidhne-air-loidhne.
  • An uairsin bidh sinn a 'gairm wsl leis an loidhne-àithne, bidh sinn a’ sgaradh an toraidh le dealadairean loidhne agus a’ gineadh airson gach fear CompletionResults, gan rèiteachadh agus teicheadh ​​​​bho charactaran leithid beàrnan agus bragan a bhiodh air an droch mhìneachadh.

Mar thoradh air an sin, cleachdaidh na sligean àithne Linux againn dìreach an aon fèin-choileanadh ri bash! Mar eisimpleir:

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

Bidh gach fèin-choileanadh a’ toirt seachad luachan a tha sònraichte don argamaid roimhe, a’ leughadh dàta rèiteachaidh leithid luchd-aoigheachd aithnichte bho WSL!

<TAB> thèid e tro na paramadairean. <Ctrl + пробел> seallaidh e na roghainnean uile a tha rim faighinn.

A bharrachd air an sin, leis gu bheil fèin-chrìochnachadh bash againn a-nis, faodaidh tu slighean Linux a chrìochnachadh gu dìreach ann an PowerShell!

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

Ann an cùisean far nach toir fèin-choileanadh bash toraidhean sam bith, tillidh PowerShell air ais gu slighean bunaiteach Windows an t-siostaim. Mar sin, ann an cleachdadh, faodaidh tu an dà shlighe a chleachdadh aig an aon àm a rèir do thoil fhèin.

co-dhùnadh

A’ cleachdadh PowerShell agus WSL, is urrainn dhuinn òrdughan Linux fhilleadh a-steach do Windows mar thagraidhean dùthchasach. Cha leig thu leas rannsachadh a dhèanamh airson Win32 a’ togail no goireasan Linux no stad a chuir air do shruth-obrach le bhith a’ dol gu slige Linux. Dìreach stàladh WSL, rèiteachadh Pròifil PowerShell и dèan liosta de na h-òrdughan a tha thu airson a thoirt a-steach! Tha fèin-choileanadh beairteach airson paramadairean àithne Linux agus Windows agus slighean faidhle na ghnìomhachd nach eil eadhon ri fhaighinn ann an òrdughan dùthchasach Windows an-diugh.

Tha an còd stòr slàn a tha air a mhìneachadh gu h-àrd, a bharrachd air stiùireadh a bharrachd airson a thoirt a-steach don t-sruth-obrach agad, ri fhaighinn an seo.

Dè na h-òrdughan Linux as fheumaile dhut? Dè na rudan cumanta eile a tha a dhìth nuair a bhios tu ag obair ann an Windows? Sgrìobh anns na beachdan no air GitHub!

Source: www.habr.com

Cuir beachd ann