Skip to content

Commit d812d9d

Browse files
committed
feat(env): 为 Sync-PathFromBash 添加非登录模式支持并改进 PATH 同步逻辑
- 默认改为非登录模式(仅从 .bashrc 加载 PATH),新增 -Login 开关启用完整登录模式 - 添加非登录模式失败时的回退逻辑,尝试显式加载 ~/.bashrc - 保留现有登录模式回退到 /etc/profile 的逻辑 - 更新函数文档和测试用例,确保兼容性和可测试性
1 parent cdc01fb commit d812d9d

4 files changed

Lines changed: 68 additions & 19 deletions

File tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
## 目标
2+
- 将 `Sync-PathFromBash` 默认改为“非登录模式”,仅从 `.bashrc` 加载 PATH;通过 `-Login` 开关启用登录模式(`bash -l`)。
3+
4+
## 影响面分析
5+
- 修改文件:`psutils/modules/env.psm1`
6+
- 风险:交互式 `.bashrc` 可能包含需要用户交互的命令;需保留回退并支持 `-WhatIf`。
7+
8+
## 设计方案
9+
- 新增参数:`[switch]$Login`(默认 false)。
10+
- 非登录模式(默认):使用 `bash -ci 'echo $PATH'` 获取仅由 `.bashrc` 配置的 PATH。
11+
- 登录模式(切换):使用 `bash -lc 'echo $PATH'` 获取完整登录环境 PATH。
12+
- 回退逻辑:
13+
- 非登录失败或空输出→尝试 `bash --noprofile --norc -c 'source ~/.bashrc 2>/dev/null; echo $PATH'`;若仍失败→返回警告。
14+
- 登录失败或空输出→回退 `bash -c 'source /etc/profile >/dev/null 2>&1; echo $PATH'`。
15+
- 保留并复用现有增强:Trim/去重、集合差集(保留顺序)、目录存在性过滤、`-Prepend`/默认后置、`-WhatIf`/`-Confirm`、结构化返回对象。
16+
- 文档与示例:更新 `.PARAMETER Login` 与 `.EXAMPLE`,增加非登录与登录示例。
17+
18+
## 实施步骤
19+
1. 在函数参数中添加 `-Login` 并改写 Bash 调用分支(默认 `bash -ci`,登录分支 `bash -lc`)。
20+
2. 添加非登录失败回退到显式 `source ~/.bashrc` 的逻辑;保留现有登录回退到 `/etc/profile`。
21+
3. 保持其余路径处理与输出逻辑不变,以减少回归风险。
22+
4. 更新函数注释的 `.DESCRIPTION`、`.PARAMETER Login`、`.EXAMPLE`。
23+
5. 更新/新增测试:验证默认非登录分支与 `-Login` 分支均能返回对象,且支持 `-WhatIf`。
24+
25+
## 验证方案
26+
- 本地执行:`Sync-PathFromBash -WhatIf`(非登录)、`Sync-PathFromBash -Login -WhatIf`(登录),确认结构化返回字段齐全、无异常。
27+
- 极端用例:`.bashrc` 为空/含交互命令时,验证回退到 `source ~/.bashrc` 的行为与日志提示。
28+
29+
请确认以上方案,确认后我将据此实现并完成测试。

‎profile/profile_unix.ps1‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ function Initialize-Environment {
157157
$env:PATH += ":/home/linuxbrew/.linuxbrew/bin/"
158158
}
159159
if ($IsLinux) {
160-
Sync-PathFromBash
160+
Sync-PathFromBash | Out-Null
161161
}
162162
if ($Minimal -or (Test-Path -Path (Join-Path $PSScriptRoot 'minimal')) -or $env:POWERSHELL_PROFILE_MINIMAL) {
163163
$SkipTools = $true

‎psutils/modules/env.psm1‎

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -431,11 +431,13 @@ function Remove-FromEnvPath {
431431
function Sync-PathFromBash {
432432
<#
433433
.SYNOPSIS
434-
同步 Bash 登录 Shell 的 PATH 到当前 PowerShell 会话。
434+
同步 Bash 的 PATH(默认非登录,从 .bashrc)到当前 PowerShell 会话。
435435
.DESCRIPTION
436-
在 Linux/macOS 上,通过调用 `bash -l` 获取完整配置后的 PATH,
437-
比较当前 PowerShell 的 PATH,追加缺失路径。支持前置/后置策略,
438-
可选过滤不存在的目录,并返回结构化结果用于编程处理。
436+
默认采用非登录模式(不加载 /etc/profile),通过 `bash -ci` 读取由 `.bashrc` 配置的 PATH,
437+
并与 PowerShell 的 PATH 对比追加缺失项。可通过 `-Login` 开启登录模式(`bash -lc`)。
438+
支持前置/后置策略、目录有效性过滤、结构化返回对象与安全预览。
439+
.PARAMETER Login
440+
启用登录模式(`bash -lc`),获取完整登录环境 PATH。
439441
.PARAMETER Prepend
440442
将缺失路径前置到 PATH 开头,使 Bash 的路径优先生效。
441443
.PARAMETER IncludeNonexistent
@@ -444,33 +446,48 @@ function Sync-PathFromBash {
444446
返回包含统计与结果的 `PSCustomObject`(默认 true)。
445447
.EXAMPLE
446448
Sync-PathFromBash -WhatIf -Verbose
447-
预览将要变更的 PATH,不实际更改,并显示详细日志。
449+
以非登录模式预览将要变更的 PATH,不实际更改,并显示详细日志。
448450
.EXAMPLE
449-
Sync-PathFromBash -Prepend -Verbose
450-
将 Bash 中缺失的目录前置到 PATH,适合优先使用 Bash 环境。
451+
Sync-PathFromBash -Login -Prepend -Verbose
452+
以登录模式将 Bash 中缺失的目录前置到 PATH,适合优先使用完整登录环境。
451453
#>
452454
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')]
453455
param(
456+
[switch]$Login,
454457
[switch]$Prepend,
455-
[switch]$Append,
456458
[switch]$IncludeNonexistent,
457459
[bool]$ReturnObject = $true
458460
)
459461

460462
try {
461463
$start = [DateTime]::UtcNow
462464
Write-Information "正在从 Bash 登录 Shell 中获取 PATH..."
463-
if ($Prepend -and $Append) { throw "同时指定 Prepend 与 Append,不支持;请二选一" }
464-
465-
$bashPathOutput = bash -l -c 'echo $PATH'
466-
$source = 'bash-login'
467-
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($bashPathOutput)) {
468-
Write-Warning "无法从 Bash 登录 Shell 获取 PATH,尝试回退方案。"
469-
$bashPathOutput = bash -c 'source /etc/profile >/dev/null 2>&1; echo $PATH'
470-
$source = 'bash-profile-fallback'
465+
$bashPathOutput = ''
466+
$source = ''
467+
if ($Login) {
468+
$bashPathOutput = bash -lc 'echo $PATH'
469+
$source = 'bash-login'
471470
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($bashPathOutput)) {
472-
Write-Warning "无法从 Bash 获取 PATH。Bash 可能未安装或存在配置错误。"
473-
return
471+
Write-Warning "无法从 Bash 登录 Shell 获取 PATH,尝试回退 /etc/profile。"
472+
$bashPathOutput = bash -c 'source /etc/profile >/dev/null 2>&1; echo $PATH'
473+
$source = 'bash-profile-fallback'
474+
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($bashPathOutput)) {
475+
Write-Warning "无法从 Bash 获取 PATH。Bash 可能未安装或存在配置错误。"
476+
return
477+
}
478+
}
479+
}
480+
else {
481+
$bashPathOutput = bash -ci 'echo $PATH'
482+
$source = 'bash-nologin-bashrc'
483+
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($bashPathOutput)) {
484+
Write-Warning "非登录模式获取 PATH 失败,尝试显式加载 ~/.bashrc。"
485+
$bashPathOutput = bash --noprofile --norc -c 'source ~/.bashrc 2>/dev/null; echo $PATH'
486+
$source = 'bash-nologin-bashrc-fallback'
487+
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($bashPathOutput)) {
488+
Write-Warning "无法从非登录模式获取 PATH。请检查 Bash 安装或 .bashrc 配置。"
489+
return
490+
}
474491
}
475492
}
476493

‎tests/Sync-PathFromBash.Tests.ps1‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,7 @@ Describe 'Sync-PathFromBash basic behavior' {
1818
It 'should support Append strategy (default) without error when WhatIf' {
1919
{ Sync-PathFromBash -WhatIf } | Should -Not -Throw
2020
}
21+
It 'should support Login branch without error when WhatIf' {
22+
{ Sync-PathFromBash -Login -WhatIf } | Should -Not -Throw
23+
}
2124
}

0 commit comments

Comments
 (0)