mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
refactor: SSHClientX.exec
This commit is contained in:
@@ -31,8 +31,8 @@ class ServerPrivateInfo {
|
||||
final List<String>? tags;
|
||||
@HiveField(7)
|
||||
final String? alterUrl;
|
||||
@HiveField(8)
|
||||
final bool? autoConnect;
|
||||
@HiveField(8, defaultValue: true)
|
||||
final bool autoConnect;
|
||||
|
||||
/// [id] of the jump server
|
||||
@HiveField(9)
|
||||
@@ -59,7 +59,7 @@ class ServerPrivateInfo {
|
||||
this.keyId,
|
||||
this.tags,
|
||||
this.alterUrl,
|
||||
this.autoConnect,
|
||||
this.autoConnect = true,
|
||||
this.jumpId,
|
||||
this.custom,
|
||||
this.wolCfg,
|
||||
@@ -75,7 +75,7 @@ class ServerPrivateInfo {
|
||||
final keyId = json['pubKeyId'] as String?;
|
||||
final tags = (json['tags'] as List?)?.cast<String>();
|
||||
final alterUrl = json['alterUrl'] as String?;
|
||||
final autoConnect = json['autoConnect'] as bool?;
|
||||
final autoConnect = json['autoConnect'] as bool? ?? true;
|
||||
final jumpId = json['jumpId'] as String?;
|
||||
final custom = json['customCmd'] == null
|
||||
? null
|
||||
@@ -128,9 +128,7 @@ class ServerPrivateInfo {
|
||||
if (alterUrl != null) {
|
||||
data['alterUrl'] = alterUrl;
|
||||
}
|
||||
if (autoConnect != null) {
|
||||
data['autoConnect'] = autoConnect;
|
||||
}
|
||||
data['autoConnect'] = autoConnect;
|
||||
if (jumpId != null) {
|
||||
data['jumpId'] = jumpId;
|
||||
}
|
||||
@@ -160,7 +158,7 @@ class ServerPrivateInfo {
|
||||
custom?.cmds != old.custom?.cmds;
|
||||
}
|
||||
|
||||
IpPort fromStringUrl() {
|
||||
(String, int) fromStringUrl() {
|
||||
if (alterUrl == null) {
|
||||
throw SSHErr(type: SSHErrType.connect, message: 'alterUrl is null');
|
||||
}
|
||||
@@ -177,7 +175,7 @@ class ServerPrivateInfo {
|
||||
if (port <= 0 || port > 65535) {
|
||||
throw SSHErr(type: SSHErrType.connect, message: 'alterUrl port error');
|
||||
}
|
||||
return IpPort(ip_, port_);
|
||||
return (ip_, port_);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -206,11 +204,6 @@ class ServerPrivateInfo {
|
||||
logoUrl: 'https://example.com/logo.png',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class IpPort {
|
||||
final String ip;
|
||||
final int port;
|
||||
|
||||
IpPort(this.ip, this.port);
|
||||
bool get isRoot => user == 'root';
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class ServerPrivateInfoAdapter extends TypeAdapter<ServerPrivateInfo> {
|
||||
keyId: fields[5] as String?,
|
||||
tags: (fields[6] as List?)?.cast<String>(),
|
||||
alterUrl: fields[7] as String?,
|
||||
autoConnect: fields[8] as bool?,
|
||||
autoConnect: fields[8] == null ? true : fields[8] as bool,
|
||||
jumpId: fields[9] as String?,
|
||||
custom: fields[10] as ServerCustom?,
|
||||
wolCfg: fields[11] as WakeOnLanCfg?,
|
||||
|
||||
@@ -34,7 +34,7 @@ class ServerProvider extends ChangeNotifier {
|
||||
final _manualDisconnectedIds = <String>{};
|
||||
|
||||
Future<void> load() async {
|
||||
// Issue #147
|
||||
// #147
|
||||
// Clear all servers because of restarting app will cause duplicate servers
|
||||
final oldServers = Map<String, Server>.from(_servers);
|
||||
_servers.clear();
|
||||
@@ -46,7 +46,7 @@ class ServerProvider extends ChangeNotifier {
|
||||
final originServer = oldServers[spi.id];
|
||||
final newServer = genServer(spi);
|
||||
|
||||
/// Issues #258
|
||||
/// #258
|
||||
/// If not [shouldReconnect], then keep the old state.
|
||||
if (originServer != null && !originServer.spi.shouldReconnect(spi)) {
|
||||
newServer.conn = originServer.conn;
|
||||
@@ -112,20 +112,20 @@ class ServerProvider extends ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
|
||||
await Future.wait(_servers.values.map((s) => _connectFn(s, onlyFailed)));
|
||||
}
|
||||
await Future.wait(_servers.values.map((s) async {
|
||||
if (onlyFailed) {
|
||||
if (s.conn != ServerConn.failed) return;
|
||||
TryLimiter.reset(s.spi.id);
|
||||
}
|
||||
|
||||
Future<void> _connectFn(Server s, bool onlyFailed) async {
|
||||
if (onlyFailed) {
|
||||
if (s.conn != ServerConn.failed) return;
|
||||
TryLimiter.reset(s.spi.id);
|
||||
}
|
||||
if (_manualDisconnectedIds.contains(s.spi.id)) return;
|
||||
|
||||
if (!(s.spi.autoConnect ?? true) && s.conn == ServerConn.disconnected ||
|
||||
_manualDisconnectedIds.contains(s.spi.id)) {
|
||||
return;
|
||||
}
|
||||
return await _getData(s.spi);
|
||||
if (s.conn == ServerConn.disconnected && !s.spi.autoConnect) {
|
||||
return;
|
||||
}
|
||||
|
||||
return await _getData(s.spi);
|
||||
}));
|
||||
}
|
||||
|
||||
Future<void> startAutoRefresh() async {
|
||||
@@ -301,16 +301,16 @@ class ServerProvider extends ChangeNotifier {
|
||||
final scriptRaw = ShellFunc.allScript(spi.custom?.cmds).uint8List;
|
||||
|
||||
try {
|
||||
final writeScriptResult = await s.client!.runForOutput(
|
||||
ShellFunc.getInstallShellCmd(spi.id),
|
||||
action: (session) async {
|
||||
final (_, writeScriptResult) = await s.client!.exec(
|
||||
(session) async {
|
||||
session.stdin.add(scriptRaw);
|
||||
session.stdin.close();
|
||||
},
|
||||
entry: ShellFunc.getInstallShellCmd(spi.id),
|
||||
);
|
||||
if (writeScriptResult.isNotEmpty) {
|
||||
ShellFunc.switchScriptDir(spi.id);
|
||||
throw String.fromCharCodes(writeScriptResult);
|
||||
throw writeScriptResult;
|
||||
}
|
||||
} on SSHAuthAbortError catch (e) {
|
||||
TryLimiter.inc(sid);
|
||||
|
||||
@@ -8,28 +8,27 @@ import 'package:server_box/data/res/provider.dart';
|
||||
|
||||
final class SystemdProvider {
|
||||
late final SSHClient _client;
|
||||
late final bool isRoot;
|
||||
|
||||
SystemdProvider.init(ServerPrivateInfo spi) {
|
||||
isRoot = spi.isRoot;
|
||||
_client = Pros.server.pick(spi: spi)!.client!;
|
||||
getUnits();
|
||||
}
|
||||
|
||||
final isBusy = false.vn;
|
||||
final isRoot = false.vn;
|
||||
final units = <SystemdUnit>[].vn;
|
||||
|
||||
Future<void> getUnits() async {
|
||||
isBusy.value = true;
|
||||
|
||||
try {
|
||||
final result = await _client.runScriptIn(_getUnitsCmd);
|
||||
final result = await _client.execForOutput(_getUnitsCmd);
|
||||
final units = result.split('\n');
|
||||
final isRootRaw = units.firstOrNull;
|
||||
isRoot.value = isRootRaw == '0';
|
||||
|
||||
final userUnits = <String>[];
|
||||
final systemUnits = <String>[];
|
||||
for (final unit in units.skip(1)) {
|
||||
for (final unit in units) {
|
||||
if (unit.startsWith('/etc/systemd/system')) {
|
||||
systemUnits.add(unit);
|
||||
} else if (unit.startsWith('~/.config/systemd/user')) {
|
||||
@@ -64,7 +63,7 @@ for unit in ${unitNames_.join(' ')}; do
|
||||
echo -n "${ShellFunc.seperator}\n\$state"
|
||||
done
|
||||
''';
|
||||
final result = await _client.runScriptIn(script);
|
||||
final result = await _client.execForOutput(script);
|
||||
final units = result.split(ShellFunc.seperator);
|
||||
|
||||
final parsedUnits = <SystemdUnit>[];
|
||||
@@ -124,17 +123,8 @@ done
|
||||
});
|
||||
return parsedUnits;
|
||||
}
|
||||
}
|
||||
|
||||
String _getIniVal(String line) {
|
||||
return line.split('=').last;
|
||||
}
|
||||
|
||||
const _getUnitsCmd = '''
|
||||
# If root, get system & user units, otherwise get user units
|
||||
uid=\$(id -u)
|
||||
echo \$uid
|
||||
|
||||
late final _getUnitsCmd = '''
|
||||
get_files() {
|
||||
unit_type=\$1
|
||||
base_dir=\$2
|
||||
@@ -149,14 +139,12 @@ get_files() {
|
||||
|
||||
get_type_files() {
|
||||
unit_type=\$1
|
||||
|
||||
base_dir=""
|
||||
if [ "\$uid" -eq 0 ]; then
|
||||
get_files \$unit_type /etc/systemd/system
|
||||
get_files \$unit_type ~/.config/systemd/user
|
||||
else
|
||||
get_files \$unit_type ~/.config/systemd/user
|
||||
fi
|
||||
|
||||
${isRoot ? """
|
||||
get_files \$unit_type /etc/systemd/system
|
||||
get_files \$unit_type ~/.config/systemd/user""" : """
|
||||
get_files \$unit_type ~/.config/systemd/user"""}
|
||||
}
|
||||
|
||||
types="service socket mount timer"
|
||||
@@ -165,3 +153,8 @@ for type in \$types; do
|
||||
get_type_files \$type
|
||||
done
|
||||
''';
|
||||
}
|
||||
|
||||
String _getIniVal(String line) {
|
||||
return line.split('=').last;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// This file is generated by fl_build. Do not edit.
|
||||
// ignore_for_file: prefer_single_quotes
|
||||
|
||||
class BuildData {
|
||||
static const String name = 'ServerBox';
|
||||
static const int build = 1058;
|
||||
static const int script = 56;
|
||||
static const String name = "ServerBox";
|
||||
static const int build = 1060;
|
||||
static const int script = 57;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user