В Linux отключена попытка применить переменные

This commit is contained in:
2026-06-04 20:04:58 +03:00
parent b6eb8026f0
commit 2565c138e4
2 changed files with 7 additions and 138 deletions

View File

@@ -77,8 +77,7 @@ dotnet run --project src/Sms.TaskTwo.Avalonia/Sms.TaskTwo.Avalonia.csproj
### Linux ### Linux
- Запись в `~/.config/environment.d/` (systemd `KEY=value`). - Запись в `~/.config/environment.d/` (systemd `KEY=value`).
- **Применить к сессии** (`ReloadEnvironment`): текущий процесс, `systemctl --user set-environment`, при наличии — `dbus-update-environment`. - **Применить к сессии** не поддерживается: переменные подхватываются после перезапуска login-сессии.
- Новые login-сессии могут потребовать перелогин — ограничение systemd.
## Предположения (ТЗ) ## Предположения (ТЗ)

View File

@@ -1,4 +1,3 @@
using System.Diagnostics;
using Sms.Environment; using Sms.Environment;
namespace Sms.Environment.Linux; namespace Sms.Environment.Linux;
@@ -6,7 +5,6 @@ namespace Sms.Environment.Linux;
public sealed class LinuxEnvironmentVariableStore : IEnvironmentVariableStore public sealed class LinuxEnvironmentVariableStore : IEnvironmentVariableStore
{ {
private const string ManagedFileName = "99-sms-task-two.conf"; private const string ManagedFileName = "99-sms-task-two.conf";
private const int SystemctlBatchSize = 32;
private readonly string _managedFilePath; private readonly string _managedFilePath;
private readonly string _environmentDirectory; private readonly string _environmentDirectory;
@@ -121,7 +119,6 @@ public sealed class LinuxEnvironmentVariableStore : IEnvironmentVariableStore
} }
System.Environment.SetEnvironmentVariable(name, null); System.Environment.SetEnvironmentVariable(name, null);
TryRunSystemctl(["--user", "unset-environment", name], out _);
} }
catch (Exception ex) when (ex is UnauthorizedAccessException or IOException) catch (Exception ex) when (ex is UnauthorizedAccessException or IOException)
{ {
@@ -131,141 +128,14 @@ public sealed class LinuxEnvironmentVariableStore : IEnvironmentVariableStore
} }
} }
public EnvironmentReloadResult ReloadEnvironment() public EnvironmentReloadResult ReloadEnvironment() =>
new()
{ {
var variables = GetUserPersistedEnvironment(); Success = false,
ApplyToCurrentProcess(variables); Message =
"Применение переменных к сессии в Linux не поддерживается. " +
if (variables.Count == 0) "Значения сохраняются в ~/.config/environment.d/ и подхватываются после перезапуска login-сессии.",
{
return new EnvironmentReloadResult
{
Success = true,
Message = "Пользовательских переменных для применения нет.",
}; };
}
var messages = new List<string>();
if (TryApplyViaSystemctl(variables, out var systemctlError))
{
messages.Add("systemd user manager обновлён (systemctl --user set-environment).");
}
else if (systemctlError is not null)
{
messages.Add($"systemctl: {systemctlError}");
}
if (TryApplyViaDbusUpdateEnvironment(variables, out var dbusError))
{
messages.Add("D-Bus session обновлён (dbus-update-environment).");
}
else if (dbusError is not null)
{
messages.Add($"dbus-update-environment: {dbusError}");
}
var processApplied = messages.Count > 0 || variables.Count > 0;
return new EnvironmentReloadResult
{
Success = processApplied,
Message = processApplied
? $"Применено {variables.Count} переменных к текущему процессу. {string.Join(' ', messages)}"
: "Не удалось применить переменные к сессии.",
};
}
private static void ApplyToCurrentProcess(IReadOnlyDictionary<string, string> variables)
{
foreach (var pair in variables)
{
System.Environment.SetEnvironmentVariable(pair.Key, pair.Value);
}
}
private static bool TryApplyViaSystemctl(
IReadOnlyDictionary<string, string> variables,
out string? errorMessage)
{
errorMessage = null;
var pairs = variables.ToList();
for (var offset = 0; offset < pairs.Count; offset += SystemctlBatchSize)
{
var arguments = new List<string> { "--user", "set-environment" };
foreach (var pair in pairs.Skip(offset).Take(SystemctlBatchSize))
{
arguments.Add($"{pair.Key}={pair.Value}");
}
if (!TryRunSystemctl(arguments, out errorMessage))
{
return false;
}
}
return true;
}
private static bool TryApplyViaDbusUpdateEnvironment(
IReadOnlyDictionary<string, string> variables,
out string? errorMessage)
{
var arguments = new List<string>();
foreach (var pair in variables)
{
arguments.Add($"{pair.Key}={pair.Value}");
}
return TryRunCommand("dbus-update-environment", arguments, out errorMessage);
}
private static bool TryRunSystemctl(IReadOnlyList<string> arguments, out string? errorMessage) =>
TryRunCommand("systemctl", arguments, out errorMessage);
private static bool TryRunCommand(
string fileName,
IReadOnlyList<string> arguments,
out string? errorMessage)
{
errorMessage = null;
try
{
var startInfo = new ProcessStartInfo
{
FileName = fileName,
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false,
};
foreach (var argument in arguments)
{
startInfo.ArgumentList.Add(argument);
}
using var process = Process.Start(startInfo);
if (process is null)
{
errorMessage = "не удалось запустить процесс";
return false;
}
var stderr = process.StandardError.ReadToEnd();
process.WaitForExit(5000);
if (process.ExitCode == 0)
{
return true;
}
errorMessage = string.IsNullOrWhiteSpace(stderr)
? $"код выхода {process.ExitCode}"
: stderr.Trim();
return false;
}
catch (Exception ex)
{
errorMessage = ex.Message;
return false;
}
}
private Dictionary<string, string> LoadManagedFile() private Dictionary<string, string> LoadManagedFile()
{ {