Как создать постоянную переменную среды для Linux в PowerShell
Как создать, установить и обновить постоянную переменную среды для Linux в PowerShell Core. Следующее решение работает правильно, но только когда я запускаю скрипт в Windows:
[Environment]::SetEnvironmentVariable("Variable", "Value", "Machine")
1 ответ
Я добавил поддержку в свойxEnvironmentVariables
Модуль PowerShell для этого. Фактическая функция PowerShell находится по адресу: Set-NixEnvironmentVariable.ps1 . Ниже приведена рабочая версия функции. YMMV, бегите с осторожностью. Это работает только при запуске из повышенного состояния (su
) какetc/environment
файл защищен.
function Set-EnvironmentVariable {
param(
[Parameter(Mandatory = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$Value
)
begin {
Write-Debug "[Begin Set-NixEnvironmentVariable]"
$environmentFile = "/etc/environment"
#region functions
# function to test for root
function Test-Root {
$isRoot = $false
$userId = . id -u
if ($userId -eq 0) {
$isRoot = $true
}
return $isRoot
}
# function to parse te environment file
function Read-EnvironmentFile {
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]$EnvironmentFile
)
$environmentVariables = [System.Collections.Specialized.OrderedDictionary]::new()
$environmentFileContent = Get-Content -Path $EnvironmentFile
foreach ($line in $environmentFileContent) {
if ($line -match "^(?<name>[A-Z_]+)=(?<value>.*)$") {
$environmentVariables.Add($matches.name, $matches.value)
# $environmentVariables[$matches.name] = $matches.value
}
}
return $environmentVariables
}
# function to convert a hashtable to a valid environment file
function ConvertTo-EnvironmentFile {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[System.Collections.Specialized.OrderedDictionary]$EnvironmentVariables
)
$stringBuilder = [System.Text.StringBuilder]::new()
# iterate over the keys in the order they are listed in the ordered dictionary, and add the resulting environment file content to the string builder
foreach ($key in $EnvironmentVariables.Keys) {
$null = $stringBuilder.AppendLine("$key=$($EnvironmentVariables[$key])")
}
return $stringBuilder.ToString()
# foreach ($key in $EnvironmentVariables.Keys) {
# $environmentFileContent += "$key=$($EnvironmentVariables[$key])"
# }
# return $environmentFileContent
}
# function to test if the environment variable already exists
function Test-EnvironmentVariableExists {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]$EnvironmentFile,
[Parameter(Mandatory = $true)]
[string]$Name
)
$environmentFileContent = Get-Content -Path $EnvironmentFile
foreach ($line in $environmentFileContent) {
if ($line -match "^(?<name>[A-Z_]+)=(?<value>.*)$") {
if ($matches.name -eq $Name) {
Write-Warning "The environment variable $Name already exists in $EnvironmentFile"
return $true
}
}
}
return $false
}
# function to add the environment variable to the environment file
function Add-EnvironmentVariable {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]$EnvironmentFile,
[Parameter(Mandatory = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$Value
)
$environmentFileContent = Get-Content -Path $EnvironmentFile
$environmentFileContent += "`n$Name=$Value"
Set-Content -Path $EnvironmentFile -Value $environmentFileContent
}
# function to update the environment variable in the environment file
function Update-EnvironmentVariable {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]$EnvironmentFile,
[Parameter(Mandatory = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$Value
)
$environmentFileContent = Get-Content -Path $EnvironmentFile
foreach ($line in $environmentFileContent) {
if ($line -match "^(?<name>[A-Z_]+)=(?<value>.*)$") {
if ($matches.name -eq $Name) {
$line = "$Name=$Value"
}
}
}
Set-Content -Path $EnvironmentFile -Value $environmentFileContent
}
# a function to check the differences between two environment files
function Compare-EnvironmentFiles {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]$EnvironmentFile1,
[Parameter(Mandatory = $true)]
[string]$EnvironmentFile2
)
$environmentFile1Content = Get-Content -Path $EnvironmentFile1
$environmentFile2Content = Get-Content -Path $EnvironmentFile2
$environmentFile1Content | Compare-Object -ReferenceObject $environmentFile2Content
}
#endregion functions
if (!(Test-Root)) {
Write-Error "This script must be run as root"
break
}
# create a backup in the user's home directory
$backupFile = "$ENV:HOME/environment.bak"
try {
Copy-Item -Path $environmentFile -Destination $backupFile -Force
} catch {
Write-Warning "Unable to create backup of $environmentFile"
break
}
# read the environment file into an ordered dictionary
$environmentVariables = Read-EnvironmentFile -EnvironmentFile $environmentFile
# test if the environment variable already exists
$environmentVariableExists = Test-EnvironmentVariableExists -EnvironmentFile $environmentFile -Name $Name
}
process {
Write-Debug "[Process Set-NixEnvironmentVariable]"
# if the environment variable already exists, update it
if ($environmentVariableExists) {
try {
Update-EnvironmentVariable -EnvironmentFile $environmentFile -Name $Name -Value $Value
} catch {
Write-Warning "Unable to update environment variable $Name in $environmentFile"
Write-Warning $PSItem.Exception.Message
Write-Warning "if the environment variable is not set correctly, you can restore the backup file at $backupFile"
break
}
} else {
# if the environment variable does not exist, add it
try {
Add-EnvironmentVariable -EnvironmentFile $environmentFile -Name $Name -Value $Value
} catch {
Write-Warning "Unable to add environment variable $Name in $environmentFile"
Write-Warning $PSItem.Exception.Message
Write-Warning "if the environment variable is not set correctly, you can restore the backup file at $backupFile"
break
}
}
}
end {
Write-Debug "[End Set-NixEnvironmentVariable]"
# clean up backup file if the only difference is the new variable
$differences = Compare-EnvironmentFiles -EnvironmentFile1 $environmentFile -EnvironmentFile2 $backupFile
if ($differences.Count -eq 1) {
Remove-Item -Path $backupFile
} else {
Write-Warning "The environment file $environmentFile has been updated"
Write-Warning "if the environment variable is not set correctly, you can restore the backup file at $backupFile"
}
}
}