环境变量管理实践

0x00 环境变量管理

环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。不同的操作系统和运行环境中对环境变量的管理方式都不同,本文通过抽象各操作系统中对环境变量的操作探索一种通过统一接口操作环境变量的方式。

每个环境变量的值是一个列表,列表中每个元素通过分割符分开。Unix 中使用 :,Windows 中使用 ;,例如最常用的 PATH 环境变量就是一个由多个路径组成的环境变量。

由于 Windows 中 : 被用作 Qualifier 可能出现在路径中,例如: C:\,所以不能使用 : 作为分隔符。

环境变量的结构模式可以于 Redis 中的 List 数据结构做类比:

  • 环境变量名对应 Key
  • 环境变量值对应 List
  • 环境变量值中的单个值对应 Element

统一接口的环境变量操作列表

方法说明
env_insert环境变量值头部加入一个元素
env_append环境变量值尾部加入一个元素
env_trim环境变量值中删除某一元素
env_amend修改环境变量
env_unset删除环境变量
env_list查询环境变量

0x01 Bash/Zsh 环境实现

类 Unix 中的环境变量没有持久化的概念,所有的环境变量作用域都只限制在当前的 Session 中,所有需要通过修改 .*rc 脚本的方式来模拟持久化。

##################################
# Environment Operate for Bash/Zsh
##################################

# add new element to environment variable insert mode
# $1 enviroment variable
# $2 new element
function env_insert()
{
    eval local env_var=\$\{${1}\-\}
    local new_element=${2%/}
    if ! echo $env_var | grep -E -q "(^|:)$new_element($|:)"; then
        eval export $1="${new_element}\${$1:+\:}\${$1-}"
    fi
}

# add new element to environment variable append mode
# $1 enviroment variable
# $2 new element
function env_append()
{
    eval local env_var=\$\{${1}\-\}
    local new_element=${2%/}
    if ! echo $env_var | grep -E -q "(^|:)$new_element($|:)"; then
        eval export $1="\${$1-}\${$1:+\:}${new_element}"
    fi
}

# trim element from environment variable
# $1 enviroment variable
# $2 trim element
function env_trim()
{
    eval local env_var=\$\{${1}\-\}
    local del_element=${2%/}
    eval export $1="$(echo ${env_var} | sed -E -e "s;(^|:)${del_element}(:|\$);\1\2;g" -e "s;^:|:\$;;g" -e "s;::;:;g")"
}

# amend environment variable
# $1 enviroment variable
# $2 amend element
function env_amend()
{
    eval export $1="$(echo $2)"
}

# unset environment variable
# $1 enviroment variable
function env_unset()
{
    eval unset $1
}

# list element from environment variable
# $1 enviroment variable
function env_list()
{
    eval local env_var=\$\{${1}\-\}
    echo -e ${env_var//:/\\n}
}


0x02 PowerShell 环境实现

Windows 中环境变量有持久化的概念,对于持久化的环境变量常规的操作方式为:

  • Run sysdm.cpl -> Advanced -> Environment Variables

Powershell 中使用 .NET API 的 Environment 模块可以很方便的操作环境变量。

非持久化的环境变量存储在 Env:\ 的 PSDrive 中,作为一种 Provider 的形式存在。

PowerShell 中可以通过指定 env_level 来决定需要操作的环境变量作用域

变量作用域说明
Process非持久化存储,作用于当前的 Session,相当于 Env:\
User持久化存储,作用于当前用户,相当于 HKCU:\Environment
Machine持久化存储,作用于整个系统,相当于 HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
<####################################
 # Environment Operate for PowerShell
 ####################################>

# ${env_level} possible values are { Prcess, User, Machine }
function internal_env_opration {
  Param (
    [Parameter(Mandatory = $true, Position = 0)] [bool]$is_insert,
    [Parameter(Mandatory = $true, Position = 1)] [string]$env_name,
    [Parameter(Mandatory = $true, Position = 2)] [String]$env_value,
    [Parameter(Mandatory = $false, Position = 3)] [String]$env_level = "Process"
  )
  if ($IsWindows -or $Env:OS) { $separator = ';' } else { $separator = ':' }
  $curr_values = [Environment]::GetEnvironmentVariable($env_name, $env_level)
  if ((-not $curr_values) -or ($curr_values -eq "")) {
    [Environment]::SetEnvironmentVariable($env_name, $env_value, $env_level)
  }
  else {
    if ($curr_values -like "*$separator*") {
      $values_array = $curr_values.split("$separator")
      foreach ($value in $values_array) {
        if ($value -eq $env_value) {
          return
        }
      }
    }
    else {
      if ($curr_values -eq $env_value) {
        return
      }
    }
    if ($is_insert) {
      [Environment]::SetEnvironmentVariable($env_name, "$env_value$separator$curr_values", $env_level)
    }
    else {
      [Environment]::SetEnvironmentVariable($env_name, "$curr_values$separator$env_value", $env_level)
    }
  }
}

function env_insert {
  Param (
    [Parameter(Mandatory = $true, Position = 0)] [string]$env_name,
    [Parameter(Mandatory = $true, Position = 1)] [String]$env_value,
    [Parameter(Mandatory = $false, Position = 2)] [String]$env_level = "Process"
  )
  internal_env_opration $true $env_name $env_value $env_level
}

function env_append {
  Param (
    [Parameter(Mandatory = $true, Position = 0)] [string]$env_name,
    [Parameter(Mandatory = $true, Position = 1)] [String]$env_value,
    [Parameter(Mandatory = $false, Position = 2)] [String]$env_level = "Process"
  )
  internal_env_opration $false $env_name $env_value $env_level
}

function env_trim {
  Param (
    [Parameter(Mandatory = $true, Position = 0)] [string]$env_name,
    [Parameter(Mandatory = $true, Position = 1)] [String]$env_value,
    [Parameter(Mandatory = $false, Position = 2)] [String]$env_level = "Process"
  )
  if ($IsWindows -or $Env:OS) { $separator = ';' } else { $separator = ':' }
  $curr_values = [Environment]::GetEnvironmentVariable($env_name, $env_level)
  if ((-not $curr_values) -or ($curr_values -eq "")) {
    return
  }
  else {
    if ($curr_values -like "*$separator*") {
      $values_array = $curr_values.split("$separator")
      foreach ($value in $values_array) {
        if (-not ($value -eq $env_value)) {
          if (-not $new_value) {
            $new_value = "$value"
          }
          else {
            $new_value += "$separator$value"
          }
        }
      }
      [Environment]::SetEnvironmentVariable($env_name, $new_value, $env_level)
    }
    else {
      if ($curr_values -eq $env_value) {
        [Environment]::SetEnvironmentVariable($env_name, $null, $env_level)
      }
    }
  }
}

function env_amend {
  Param (
    [Parameter(Mandatory = $true, Position = 0)] [string]$env_name,
    [Parameter(Mandatory = $true, Position = 1)] [String]$env_value,
    [Parameter(Mandatory = $false, Position = 2)] [String]$env_level = "Process"
  )
  [Environment]::SetEnvironmentVariable($env_name, $env_value, $env_level)
}

function env_unset {
  Param (
    [Parameter(Mandatory = $true, Position = 0)] [string]$env_name,
    [Parameter(Mandatory = $false, Position = 1)] [String]$env_level = "Process"
  )
  [Environment]::SetEnvironmentVariable($env_name, $null, $env_level)
}

function env_list {
  Param (
    [Parameter(Mandatory = $true, Position = 0)] [string]$env_name,
    [Parameter(Mandatory = $false, Position = 1)] [String]$env_level = "Process"
  )
  if ($IsWindows -or $Env:OS) { $separator = ';' } else { $separator = ':' }
  $curr_values = [Environment]::GetEnvironmentVariable($env_name, $env_level)
  if (($curr_values) -and (-not $curr_values -eq "")) {
    if ($curr_values -like "*$separator*") {
      $values_array = $curr_values.split("$separator")
      foreach ($value in $values_array) {
        Write-Host "$value"
      }
    }
    else {
      Write-Host "$curr_values"
    }
  }
}


参考文档

  1. PowerShell: View/Set Environment Variables
  2. How To Work with Environment Variables in PowerShell
  3. https://en.wikipedia.org/wiki/Windows_Registry
  4. Microsoft Docs -> PowerShell -> About Environment Variables
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页