-
Notifications
You must be signed in to change notification settings - Fork 4
/
PsUWI.psm1
executable file
·306 lines (275 loc) · 12.3 KB
/
PsUWI.psm1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
function New-UbuntuWSLInstance {
<#
.SYNOPSIS
Create a new Ubuntu instance on WSL
.DESCRIPTION
Create a new Ubuntu instance on WSL. Windows 10 2004 only for now.
.PARAMETER Release
The Ubuntu release you want to use to create the instance. Default is focal.
.PARAMETER Version
The WSL version you want to use. Default is 1.
.PARAMETER Force
If specified, a new WSL tarball will always be downloaded even if it exists.
.PARAMETER NoUpdate
If specified, it will not update during the creation.
.PARAMETER NoUpgrade
If specified, it will only update but not upgrade during the creation.
.PARAMETER RootOnly
If specified, no new user will be created.
.PARAMETER EnableSource
If specified, all source repositories in `/etc/apt/sources.list` will be enabled.
.PARAMETER EnableProposed
If specified, Ubuntu Proposed repository will be enabled. By default selective is enabled.
.PARAMETER DisableSelective
If specified, Selective Proposed repostiory will be disabled.
.PARAMETER AdditionalPPA
The PPA you want to include by default. Separate each PPA by comma.
.PARAMETER AptOutput
If specified, apt output will be shown.
.PARAMETER Silent
If specified, all ouput will not be printed out. AptOutput will be ignored when using this
.PARAMETER NonInteractive
If specified, it will return the name of the created distro instead of going into the interactive prompt
.PARAMETER AdditionalPkg
The packages you want to include by default. Separate each package by comma.
.EXAMPLE
New-UbuntuWSLInstance -Release bionic
# Create a Ubuntu Bionic instance on WSL1
.EXAMPLE
New-UbuntuWSLInstance -Release xenial -Version 2 -RootOnly
# Create an Ubuntu Xenial instance on WSL2 without creating a user account
.EXAMPLE
New-UbuntuWSLInstance -Version 2 -NoUpdate
# Create an Ubuntu Focal instance on WSL2 without any update
.EXAMPLE
New-UbuntuWSLInstance -Release eoan -Force
# Create an Ubuntu Eoan instance on WSL1 and download the WSL tarball even if it already exists
.LINK
https://github.com/patrick330602/PsUWI
#>
[cmdletbinding()]
Param (
[Parameter(Mandatory = $false)]
[string]$Release = 'focal',
[Parameter(Mandatory = $false)]
[ValidateSet('1', '2')]
[string]$Version = '2',
[Parameter(Mandatory = $false)]
[switch]$Force,
[Parameter(Mandatory = $false)]
[switch]$NoUpdate,
[Parameter(Mandatory = $false)]
[switch]$NoUpgrade,
[Parameter(Mandatory = $false)]
[switch]$RootOnly,
[Parameter(Mandatory = $false)]
[string]$AdditionalPPA,
[Parameter(Mandatory = $false)]
[switch]$EnableSource,
[Parameter(Mandatory = $false)]
[switch]$EnableProposed,
[Parameter(Mandatory = $false)]
[switch]$DisableSelective,
[Parameter(Mandatory = $false)]
[switch]$AptOutput,
[Parameter(Mandatory = $false)]
[switch]$Silent,
[Parameter(Mandatory = $false)]
[switch]$NonInteractive,
[Parameter(Mandatory = $false)]
[string]$AdditionalPkg
)
Process {
function Write-IfNotSilent {
[cmdletbinding()]
Param (
[Parameter(Mandatory = $true)]
[string]$Text
)
if (-not $Silent) {
Write-Host "# $Text" -ForegroundColor DarkYellow
}
}
function Stop-Honking {
if ($AptOutput -and (-not $Silent)) {
return ""
}
else {
return "-qq"
}
}
Write-IfNotSilent "Let the journey begins!"
$TmpName = -join ((65..90) + (97..122) | Get-Random -Count 10 | ForEach-Object { [char]$_ })
$SysArchName = ($env:PROCESSOR_ARCHITECTURE).ToLower()
if ( -not ( ( $SysArchName -eq "amd64" ) -or ( $SysArchName -eq "arm64" ) ) ) {
throw [System.NotSupportedException] "The architecture $SysArchName is not supported."
}
if ( ( $Release -eq "xenial" ) -and ( $SysArchName -eq "arm64" ) ) {
throw [System.NotSupportedException] "Ubuntu Xenial does not support architecture arm64."
}
Write-IfNotSilent "Your system architecture is $SysArchName"
$HomePath = $env:HOME
if (-not $HomePath) {
$HomePath = "$($env:HOMEDRIVE)$($env:HOMEPATH)"
}
if ( -not (Test-Path -Path "$HomePath\.mbw" -PathType Container ) ) {
mkdir -Path "$HomePath\.mbw" | Out-Null
}
if ( -not (Test-Path -Path "$HomePath\.mbw\.tarball" -PathType Container ) ) {
mkdir -Path "$HomePath\.mbw\.tarball" | Out-Null
}
if ( Test-Path -LiteralPath "$HomePath\.mbw\.tarball\$Release-$SysArchName.tar.gz" -PathType Leaf ) {
if ( $Force ) {
Write-IfNotSilent "WSL tarball for $Release($SysArchName) found but -Force passed. Redownloading..."
$download_start_time = Get-Date
Invoke-WebRequest -Uri "http://cloud-images.ubuntu.com/$Release/current/$Release-server-cloudimg-$SysArchName-wsl.rootfs.tar.gz" -OutFile "$HomePath\.mbw\.tarball\$Release-$SysArchName.tar.gz"
Write-IfNotSilent "Download completed for the WSL tarball for $Release($SysArchName). Time taken: $((Get-Date).Subtract($download_start_time).Seconds) second(s)"
}
else {
Write-IfNotSilent "WSL tarball for $Release ($SysArchName) found, skip downloading"
}
}
else {
Write-IfNotSilent "WSL tarball for $Release ($SysArchName) not found. Downloading..."
$download_start_time = Get-Date
Invoke-WebRequest -Uri "http://cloud-images.ubuntu.com/$Release/current/$Release-server-cloudimg-$SysArchName-wsl.rootfs.tar.gz" -OutFile "$HomePath\.mbw\.tarball\$Release-$SysArchName.tar.gz"
Write-IfNotSilent "Download completed for the WSL tarball for $Release($SysArchName). Time taken: $((Get-Date).Subtract($download_start_time).Seconds) second(s)"
}
# get absolute unique TmpName
Do {
$tmpname_exist = $false
foreach ($i in $inst_list) {
if ($i.ID -eq "$TmpName") { $tmpname_exist = $true }
}
if ( $tmpname_exist -eq $true ) { $TmpName = -join ((65..90) + (97..122) | Get-Random -Count 10 | ForEach-Object { [char]$_ }) }
} until ($tmpname_exist -eq $false)
Write-IfNotSilent "Creating instance ubuntu-$TmpName (Using Ubuntu $Release and WSL$Version)...."
wsl.exe --import ubuntu-$TmpName "$HomePath\.mbw\ubuntu-$TmpName" "$HomePath\.mbw\.tarball\$Release-amd64.tar.gz"
if (-not (wsl.exe --set-version ubuntu-$TmpName $Version)){
Write-IfNotSilent "You are using a system that do not support WSL2, keep in WSL1"
}
if ($EnableSource) {
Write-IfNotSilent "Enabling Ubuntu source repository...."
Write-IfNotSilent "-NoUpdate will be ignored if passed"
wsl.exe -d ubuntu-$TmpName sed -i `"s`|`# deb-src`|deb-src`|g`" /etc/apt/sources.list
}
if ($EnableProposed) {
Write-IfNotSilent "Enabling Ubuntu Proposed repository...."
Write-IfNotSilent "-NoUpdate will be ignored if passed"
wsl.exe -d ubuntu-$TmpName echo -e `"`# Enable Ubuntu proposed archive\ndeb http`://archive.ubuntu.com/ubuntu/ `$`(lsb_release `-cs`)-proposed restricted main multiverse universe`" `> /etc/apt/sources.list.d/ubuntu-`$`(lsb_release `-cs`)-proposed.list
if ( $SysArchName -eq "arm64" ) {
wsl.exe -d ubuntu-$TmpName echo -e `"`# Enable Ubuntu proposed archive\ndeb http`://ports.ubuntu.com/ubuntu-ports `$`(lsb_release `-cs`)-proposed restricted main multiverse universe`" `> /etc/apt/sources.list.d/ubuntu-`$`(lsb_release `-cs`)-proposed.list
}
if (-not $DisableSelective) {
wsl.exe -d ubuntu-$TmpName echo -e `"`# Configure apt to allow selective installs of packages `from proposed\nPackage: `*\nPin`: release a`=`$`(lsb_release `-cs`)-proposed\nPin-Priority`: 400`" `>`> /etc/apt/preferences.d/proposed-updates
}
}
$quiet_param = Stop-Honking
if ( -not $NoUpdate -or ($EnableSource -or $EnableProposed) ) {
Write-IfNotSilent "Updating ubuntu-$TmpName...."
wsl.exe -d ubuntu-$TmpName apt-get update $quiet_param | Out-Host
if (-not $NoUpgrade){
wsl.exe -d ubuntu-$TmpName apt-get upgrade -y $quiet_param | Out-Host
}
}
if ((-not $RootOnly) -or (-not $NonInteractive)) {
Write-IfNotSilent "Creating user '$env:USERNAME' for ubuntu-$TmpName...."
wsl.exe -d ubuntu-$TmpName /usr/sbin/useradd -m -s "/bin/bash" $env:USERNAME
wsl.exe -d ubuntu-$TmpName passwd -q -d $env:USERNAME
wsl.exe -d ubuntu-$TmpName echo `"$env:USERNAME ALL=`(ALL`:ALL`) NOPASSWD: ALL`" `| tee -a /etc/sudoers.d/$env:USERNAME `>/dev/null
wsl.exe -d ubuntu-$TmpName /usr/sbin/usermod -a -G adm,dialout,cdrom,floppy,sudo,audio,dip,video,plugdev,netdev $env:USERNAME
}
if ($AdditionalPPA) {
$ppa_array = $AdditionalPPA -split ","
foreach ($appa in $ppa_array) {
Write-IfNotSilent "Adding additional PPA '$appa'...."
wsl.exe -d ubuntu-$TmpName /usr/bin/apt-add-repository -y "ppa:$appa" | Out-Host
wsl.exe -d ubuntu-$TmpName apt-get update $quiet_param | Out-Host
wsl.exe -d ubuntu-$TmpName apt-get upgrade -y $quiet_param | Out-Host
}
}
if ($AdditionalPkg) {
$pkg_array = $AdditionalPkg -split ","
foreach ($apkg in $pkg_array) {
Write-IfNotSilent "Adding package '$apkg'...."
wsl.exe -d ubuntu-$TmpName apt-get install $quiet_param -y $apkg | Out-Host
}
}
if ( -not $RootOnly ) {
$tmp_dis_name = (Get-ChildItem HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\ | Get-ItemProperty | Where-Object {$_.'DistributionName' -eq "ubuntu-$TmpName"})[0].PSChildName
Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\$tmp_dis_name" -Name DefaultUid -Value 1000 -Force
}
Write-IfNotSilent "You are ready to rock!"
if ($NonInteractive) {
return "$TmpName"
}
else {
wsl.exe -d ubuntu-$TmpName
}
}
}
function New-NonInteractiveUbuntuInstance {
$output = New-UbuntuWSLInstance -NonInteractive $args
return $output[-1]
}
function Remove-UbuntuWSLInstance {
<#
.SYNOPSIS
Remove an Ubuntu instance on WSL
.DESCRIPTION
Remove an Ubuntu instance on WSL
.PARAMETER Id
The ID of the instance, after the name of distro "ubuntu-".
.EXAMPLE
Remove-UbuntuWSLInstance -Id AbcdEFGhiJ
# Remove an instance called ubuntu-AbcdEFGhiJ
.LINK
https://github.com/patrick330602/PsUWI
#>
[cmdletbinding()]
Param (
[Parameter(Mandatory = $true)]
[string]$Id
)
Process {
$HomePath = $env:HOME
if (-not $HomePath) {
$HomePath = "$($env:HOMEDRIVE)$($env:HOMEPATH)"
}
if ( -not ( Get-ChildItem "$HomePath\.mbw" | Select-String "$Id" ) ) {
throw [System.IO.FileNotFoundException] "$Id not found."
}
Write-Host "# Removing instance ubuntu-$Id..." -ForegroundColor DarkYellow
Write-Host "# Terminating instance ubuntu-$Id..." -ForegroundColor DarkYellow
wsl.exe -t ubuntu-$Id
Write-Host "# Unregistering instance ubuntu-$Id..." -ForegroundColor DarkYellow
wsl.exe --unregister ubuntu-$Id
Write-Host "# Cleanup..." -ForegroundColor DarkYellow
Remove-Item "$HomePath\.mbw\ubuntu-$Id" -Force -Recurse
Remove-Item "$Env:AppData\Microsoft\Windows\Start Menu\Programs\ubuntu-$Id" -Force -Recurse
Write-Host "# Removed instance ubuntu-$Id." -ForegroundColor DarkYellow
}
}
function Remove-AllUbuntuWSLInstances {
<#
.SYNOPSIS
Remove all Ubuntu instances on WSL
.DESCRIPTION
Remove all Ubuntu instances on WSL
.EXAMPLE
Remove-AllUbuntuWSLInstances
# Remove all instances
.LINK
https://github.com/patrick330602/PsUWI
#>
$HomePath = $env:HOME
if (-not $HomePath) {
$HomePath = "$($env:HOMEDRIVE)$($env:HOMEPATH)"
}
Write-Host "# Removing all instances..." -ForegroundColor DarkYellow
$UbuntuDistroList = @(Get-ChildItem "$HomePath\.mbw" -Filter ubuntu-*)
Foreach ($i in $UbuntuDistroList) {
Remove-UbuntuWSLInstance -Id ($i.BaseName).split('-')[1]
}
Write-Host "# Removed all instances." -ForegroundColor DarkYellow
}