Tipiska programma izstrÄdÄtÄjiem Windows: āKÄpÄc Å”eit joprojÄm nav <ŠŠ”Š¢ŠŠŠ¬Š¢Š Š¢Š£Š¢ ŠŠ®ŠŠŠŠ£Š® ŠŠŠŠŠŠŠ£ LINUX>?Ā». ŠŃŠ“Ń ŃŠ¾ Š¼Š¾ŃŠ½Š¾Šµ ŠæŃŠ¾Š»ŠøŃŃŃŠ²Š°Š½ŠøŠµ less vai ierastie rÄ«ki grep vai sed, izstrÄdÄtÄji Windows vÄlas viegli piekļūt Ŕīm komandÄm ikdienas darbÄ.
ir bÅ«tiski uzlabojusi Å”o situÄciju. TÄ Ä¼auj izsaukt Linux komandas no Windows, tÄs proksÄjot caur wsl.exe (piemÄram, wsl ls). Lai gan tas ir bÅ«tisks uzlabojums, Å”Äds risinÄjums cieÅ” no vairÄkiem trÅ«kumiem.
- VispÄrÄja pievienoÅ”ana
wslir nogurdinoÅ”a un dabiski nejauka. - Windows ceļi argumentu sarakstÄ ne vienmÄr strÄdÄ, jo atpakaļ slÄ«psvÄ«tras tiek interpretÄtas kÄ escape simboli, nevis katalogu dalÄ«tÄji.
- Windows ceļi argumentu sarakstÄ netiek pÄrvÄrsti atbilstoÅ”ajÄ WSL piekļuves punktÄ.
- NekÄdas noklusÄjuma opcijas WSL profilos ar aliasiem un vides mainÄ«gajiem netiek Åemtas vÄrÄ.
- Linux ceļu pabeigŔana netiek atbalstīta.
- Komandu pabeigŔana netiek atbalstīta.
- Argumentu pabeigŔana netiek atbalstīta.
TÄdÄjÄdi Linux komandas Windows sistÄmÄ tiek uztvertas kÄ otro Ŕķiru pilsoÅi ā un tÄs ir grÅ«tÄk izmantot nekÄ vietÄjÄs komandas. Lai izlÄ«dzinÄtu viÅu tiesÄ«bas, ir jÄatrisina uzskaitÄ«tÄs problÄmas.
PowerShell funkciju apvalki
Ar PowerShell funkciju apvalku palÄ«dzÄ«bu mÄs varam pievienot komandu automÄtisku pabeigÅ”anu un novÄrst priekÅ”nosacÄ«jumu nepiecieÅ”amÄ«bu, wsl, tulkojot Windows ceļus WSL ceļos. GalvenÄs prasÄ«bas apvalkiem ir:
- Katram Linux komandam jÄbÅ«t vienam funkciju apvalkam ar to paÅ”u nosaukumu.
- Apvalkam jÄatzÄ«st Windows ceļi, kas nodoti kÄ argumenti, un jÄpÄrveido tie par WSL ceļiem.
- Apvalkam jÄizsauc
wslar attiecÄ«gu Linux komandu par jebkuru caurlaides ievadi un jÄpÄrsÅ«ta jebkuri komandrindas argumenti, kas nodoti funkcijai.
KÄ Å”is Å”ablons var tikt piemÄrots jebkurai komandai, mÄs varam abstrahÄt Å”o apvalku definÄ«ciju un dinamiski Ä£enerÄt tos no komandu saraksta importam.
# 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 ' ')
}
}
"@
} Saraksts $command nosaka komandas importÄÅ”anai. PÄc tam mÄs dinamiski Ä£enerÄjam funkciju apvalku katrai no tÄm, izmantojot komandu Invoke-Expression (sÄkumÄ izÅemot jebkurus aliasus, kas varÄtu konfliktÄt ar funkciju).
Funkcija pÄrlÅ«ko komandrindas argumentus, nosaka Windows ceļus, izmantojot komandas Split-Path un Test-Path, un pÄc tam tos pÄrvÄrÅ” WSL ceļos. MÄs palaidÄm ceļus caur palÄ«gfunkciju Format-WslArgument, kuru definÄsim vÄlÄk. TÄ aizsargÄ speciÄlos simbolus, piemÄram, atstarpes un iekavas, kas citÄdi tiktu nepareizi interpretÄti.
Visbeidzot, nododam wsl ievades cauruli un jebkurus komandrindas argumentus.
Izmantojot Å”Ädus ietvarus, varat izsaukt savas iecienÄ«tÄkÄs Linux komandas dabiski, nepievienojot prefiksu wsl un neuztraucoties, kÄ ceļi tiks pÄrvÄrsti:
man bashless -i $profile.CurrentUserAllHostsls -Al C:Windows | lessgrep -Ein error *.logtail -f *.log
Å eit ir parasts komandu kopums, bet jÅ«s varat izveidot apvalku jebkurai Linux komandai, vienkÄrÅ”i pievienojot to sarakstam. Ja jÅ«s pievienosiet Å”o kodu savam PowerShell, Ŕīs komandas bÅ«s pieejamas katrÄ PowerShell sesijÄ, tÄpat kÄ vietÄjÄs komandas!
NoklusÄjuma opcijas
Linux ir pierasts definÄt aliasus un/vai vides mainÄ«gos profilos (login profile), nosakot noklusÄjuma parametrus bieži lietotÄm komandÄm (piemÄram, alias ls=ls -AFh vai export LESS=-i). Viens no trÅ«kumiem, izmantojot neinteraktÄ«vu apvalku wsl.exe ir tas, ka profili netiek ielÄdÄti, tÄpÄc Å”ie noklusÄjuma parametri nav pieejami (t.i., ls WSL un wsl ls uzvedÄ«sies savÄdÄk ar iepriekÅ” noteikto aliasu).
PowerShell nodroÅ”ina , standarta mehÄnisms, lai noteiktu noklusÄjuma parametrus, bet tikai komandletiem un paplaÅ”inÄtÄm funkcijÄm. Protams, varam no mÅ«su apvalkiem izveidot paplaÅ”inÄtas funkcijas, bet tas radÄ«s liekas sarežģījumus (tÄdÄjÄdi PowerShell sasaistÄ«s daļÄjas parametru nosaukumu (piemÄram, -a sasaistÄs ar -ArgumentList), kas radÄ«s konfliktus ar Linux komandÄm, kas pieÅem daļÄjus nosaukumus kÄ argumentus), un sintakse noklusÄjuma vÄrtÄ«bu noteikÅ”anai nebÅ«s vispiemÄrotÄkÄ (lai noteiktu noklusÄjuma argumentus, parametra nosaukumam jÄbÅ«t atslÄgÄ, nevis tikai komandas nosaukumam).
TomÄr ar nelielu mÅ«su apvalku izmaiÅu mÄs varam ieviest modeli, kas ir lÄ«dzÄ«gs $PSDefaultParameterValues, un iekļaut noklusÄjuma parametrus Linux komandÄm!
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 ' ')
}
} PÄrsÅ«tot $WslDefaultParameterValues komandrÄ mÄs nosÅ«tÄm parametrus caur wsl.exe. ZemÄk norÄdÄ«ts, kÄ pievienot instrukcijas PowerShell profilam, lai iestatÄ«tu noklusÄjuma parametrus. Tagad mÄs to varam izdarÄ«t!
$WslDefaultParameterValues["grep"] = "-E"
$WslDefaultParameterValues["less"] = "-i"
$WslDefaultParameterValues["ls"] = "-AFh --group-directories-first" Jo parametri tiek modelÄti pÄc $PSDefaultParameterValues, jÅ«s varat uz laiku, iestatot atslÄgu "Disabled" uz vÄrtÄ«bu $true. Papildu priekÅ”rocÄ«ba atseviŔķai Hash tabulai ir iespÄja atspÄjot $WslDefaultParameterValues atseviŔķi no $PSDefaultParameterValues.
AutomÄtiskÄ pabeigÅ”ana argumentiem
PowerShell ļauj reÄ£istrÄt argumentu pabeidotÄjus, izmantojot komandu Register-ArgumentCompleter. Bash ir jaudÄ«gas . WSL ļauj izsaukt bash no PowerShell. Ja mÄs varam reÄ£istrÄt argumentu pabeidotÄjus savÄm funkciju konsolÄm PowerShell un izsaukt bash, lai izveidotu pabeigÅ”anas, tad mÄs iegÅ«sim pilnÄ«gu argumentu automÄtisko pabeigÅ”anu ar tÄdu paÅ”u precizitÄti kÄ paÅ”Ä bash!
# 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]
}
}Kods ir nedaudz blÄ«vs bez izpratnes par dažÄm iekÅ”ÄjÄm bash funkcijÄm, bet galvenokÄrt mÄs darÄm sekojoÅ”o:
- ReÄ£istrÄjam argumentu pabeidotÄju visÄm mÅ«su funkciju apvalku, nododot sarakstu
$commandsparametrÄ-CommandNamelaiRegister-ArgumentCompleter. - SaskaÅojam katru komandu ar funkciju apvalku, ko bash izmanto automÄtiskai pabeigÅ”anai (specifikÄciju noteikÅ”anai automÄtiskai pabeigÅ”anai bash tiek izmantots
$F, saÄ«sinÄjums nocomplete -F). - PÄrvÄrÅ”am PowerShell argumentus
$wordToComplete,$commandAstun$cursorPositionformÄtÄ, ko sagaida bash automÄtiskÄs pabeigÅ”anas funkcijas saskaÅÄ ar bash. - SastÄdÄm komandrindas komandu, lai nodotu
wsl.exe, kas nodroÅ”ina pareizu vides iestatÄ«jumu, izsauc attiecÄ«go automÄtiskÄs pabeigÅ”anas funkciju un izvada rezultÄtus ar lÄ«niju sadalÄ«jumu. - Tad izsaucam
wslar komandrindu, sadalÄm rezultÄtu pa rindÄm un Ä£enerÄjam katramCompletionResults, sakÄrtojot tos un izvairoties no simboliem, piemÄram, atstarpÄm un iekavÄm, kas citÄdi tiktu nepareizi interpretÄti.
Galu galÄ mÅ«su Linux komandrindas apvalki izmantos tieÅ”i tÄdu paÅ”u automÄtisko pabeigÅ”anu kÄ bash! PiemÄram:
ssh -c -J -m -O -o -Q -w -b
Katram automÄtiskajam pabeigÅ”anai ir pieejami iepriekÅ”ÄjÄ argumenta specifiski vÄrtÄ«bas, nolasot konfigurÄcijas datus, piemÄram, zinÄmÄs viesu resursus no WSL!
<TAB> cikliski pÄrskatÄ«s parametrus. <Ctrl + ŠæŃŠ¾Š±ŠµŠ»> parÄdÄ«s visus pieejamos variantus.
TurklÄt, tagad, kad mums darbojas bash automÄtiskÄ pabeigÅ”ana, jÅ«s varat automÄtiski pabeigt Linux ceļus tieÅ”i PowerShell!
less /etc/ls /usr/share/vim ~/\.bash
Ja gadÄ«jumos, kad bash automÄtiskÄ pabeigÅ”ana nenodroÅ”ina rezultÄtus, PowerShell atgriežas pie noklusÄjuma sistÄmas ar Windows ceļiem. TÄdÄjÄdi jÅ«s varat praktiski vienlaikus izmantot abus ceļus pÄc jÅ«su izvÄles.
SecinÄjums
Ar PowerShell un WSL mÄs varam integrÄt Linux komandas Windows kÄ vietÄjÄs lietojumprogrammas. Nav nepiecieÅ”ams meklÄt Win32 versijas vai Linux utilÄ«tus vai pÄrtraukt darba plÅ«smu, pÄrejot uz Linux komandu rindu. VienkÄrÅ”i , konfigurÄjiet un ! BagÄtÄ«ga automÄtiskÄ pabeigÅ”ana komandparametriem un ceļiem uz failiem Linux un Windows ā Ŕī ir funkcionalitÄte, kÄda Å”odien pat nav vietÄjÄs Windows komandÄs.
Pilnais izstrÄdÄtais kods, kas aprakstÄ«ts iepriekÅ”, kÄ arÄ« papildu ieteikumi tÄ integrÄÅ”anai darba plÅ«smÄ ir pieejami. .
Kuras Linux komandas jÅ«s uzskatÄt par visnoderÄ«gÄkajÄm? KÄdas citas ierastas lietas trÅ«kst, strÄdÄjot Windows? Rakstiet komentÄros vai !
Avots: habr.com
