From 9b7d33369a459e725fbd39ba560fdc5bfdcc0179 Mon Sep 17 00:00:00 2001 From: Junyuan Feng Date: Fri, 29 Apr 2022 11:59:27 +0800 Subject: [PATCH] fix - docker ps item parse - parse issue in fish (shell) - make.dart path --- lib/data/model/docker/ps.dart | 10 +++-- lib/data/provider/docker.dart | 25 ++++++----- lib/data/provider/server.dart | 85 ++++++++++++++++++++++------------- lib/data/res/build_data.dart | 6 +-- lib/view/page/docker.dart | 2 +- make.dart | 14 +++--- 6 files changed, 87 insertions(+), 55 deletions(-) diff --git a/lib/data/model/docker/ps.dart b/lib/data/model/docker/ps.dart index 8457eea4..c848c52c 100644 --- a/lib/data/model/docker/ps.dart +++ b/lib/data/model/docker/ps.dart @@ -11,8 +11,7 @@ class DockerPsItem { this.status, this.ports, this.name); DockerPsItem.fromRawString(String rawString) { - List parts = rawString.split(' '); - parts.removeWhere((element) => element.isEmpty); + List parts = rawString.split(RegExp(' +')); parts = parts.map((e) => e.trim()).toList(); containerId = parts[0]; @@ -20,7 +19,7 @@ class DockerPsItem { command = parts[2].trim(); created = parts[3]; status = parts[4]; - if (running) { + if (running && parts.length > 6) { ports = parts[5]; name = parts[6]; } else { @@ -30,4 +29,9 @@ class DockerPsItem { } bool get running => status.contains('Up '); + + @override + String toString() { + return 'DockerPsItem<$containerId@$name>'; + } } diff --git a/lib/data/provider/docker.dart b/lib/data/provider/docker.dart index 46aaf09a..2f534324 100644 --- a/lib/data/provider/docker.dart +++ b/lib/data/provider/docker.dart @@ -3,9 +3,11 @@ import 'package:toolbox/core/extension/uint8list.dart'; import 'package:toolbox/core/provider_base.dart'; import 'package:toolbox/data/model/docker/ps.dart'; +final dockerNotFound = RegExp('(command not found | Unknown command)'); + class DockerProvider extends BusyProvider { SSHClient? client; - List? running; + List? items; String? version; String? edition; String? error; @@ -15,7 +17,7 @@ class DockerProvider extends BusyProvider { void clear() { client = null; error = null; - running = null; + items = null; version = null; edition = null; } @@ -28,6 +30,11 @@ class DockerProvider extends BusyProvider { } final verRaw = await client!.run('docker version').string; + if (verRaw.contains(dockerNotFound)) { + error = 'docker not found'; + notifyListeners(); + return; + } final verSplit = verRaw.split('\n'); if (verSplit.length < 3) { error = 'invalid version'; @@ -42,19 +49,15 @@ class DockerProvider extends BusyProvider { } final raw = await client!.run('docker ps -a').string; - if (raw.contains('command not found')) { - error = 'docker not found'; - notifyListeners(); - return; - } + final lines = raw.split('\n'); + lines.removeAt(0); + lines.removeWhere((element) => element.isEmpty); try { - final lines = raw.split('\n'); - lines.removeAt(0); - lines.removeWhere((element) => element.isEmpty); - running = lines.map((e) => DockerPsItem.fromRawString(e)).toList(); + items = lines.map((e) => DockerPsItem.fromRawString(e)).toList(); } catch (e) { error = e.toString(); + rethrow; } finally { notifyListeners(); } diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index 7a767d28..b4f559fc 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -29,6 +29,18 @@ List loadIndentity(String key) { return SSHKeyPair.fromPem(key); } +const shellCmd = "cat /proc/net/dev && date +%s \necho A====A \n " + "cat /etc/os-release | grep PRETTY_NAME \necho A====A \n" + "cat /proc/stat | grep cpu \necho A====A \n" + "uptime \necho A====A \n" + "cat /proc/net/snmp \necho A====A \n" + "df -h \necho A====A \n" + "free -m \necho A====A \n" + "cat /sys/class/thermal/thermal_zone*/type \necho A====A \n" + "cat /sys/class/thermal/thermal_zone*/temp"; +const shellPath = '.serverbox.sh'; +final cpuTempReg = RegExp('(x86_pkg_temp|cpu_thermal)'); + class ServerProvider extends BusyProvider { List _servers = []; List get servers => _servers; @@ -90,15 +102,9 @@ class ServerProvider extends BusyProvider { _getData(spi); return; } - try { - await Future.wait(_servers.map((s) async { - await _getData(s.info); - })); - } catch (e) { - if (e is! RangeError) { - rethrow; - } - } + await Future.wait(_servers.map((s) async { + await _getData(s.info); + })); } Future startAutoRefresh() async { @@ -167,33 +173,37 @@ class ServerProvider extends BusyProvider { logger.info( 'Connected to [${spi.name}] in [${time2.difference(time1).toString()}].'); _servers[idx].connectionState = ServerConnectionState.connected; - notifyListeners(); + _servers[idx] + .client! + .run("echo '$shellCmd' > $shellPath && chmod +x $shellPath"); } catch (e) { _servers[idx].connectionState = ServerConnectionState.failed; _servers[idx].status.failedInfo = e.toString() + ' ## '; - notifyListeners(); logger.warning(e); + } finally { + notifyListeners(); } } + + // if client is null, return final si = _servers[idx]; + if (si.client == null) return; + final raw = await si.client!.run("sh $shellPath").string; + final lines = raw.split('A====A').map((e) => e.trim()).toList(); + try { - if (si.client == null) return; - final raw = await si.client! - .run( - r"cat /proc/net/dev && date +%s && echo 'A====A' && cat /etc/os-release | grep PRETTY_NAME && echo 'A====A' && cat /proc/stat | grep cpu && echo 'A====A' && paste <(cat /sys/class/thermal/thermal_zone*/type) <(cat /sys/class/thermal/thermal_zone*/temp) | column -s $'\t' -t | sed 's/\(.\)..$/.\1°C/' && echo 'A====A' && uptime && echo 'A====A' && cat /proc/net/snmp && echo 'A====A' && df -h && echo 'A====A' && free -m") - .string; - final lines = raw.split('A====A').map((e) => e.trim()).toList(); - _getCPU(spi, lines[2], lines[3]); - _getMem(spi, lines[7]); + _getCPU(spi, lines[2], lines[7], lines[8]); + _getMem(spi, lines[6]); _getSysVer(spi, lines[1]); - _getUpTime(spi, lines[4]); - _getDisk(spi, lines[6]); - _getTcp(spi, lines[5]); + _getUpTime(spi, lines[3]); + _getDisk(spi, lines[5]); + _getTcp(spi, lines[4]); _getNetSpeed(spi, lines[0]); } catch (e) { _servers[idx].connectionState = ServerConnectionState.failed; servers[idx].status.failedInfo = e.toString(); logger.warning(e); + rethrow; } finally { notifyListeners(); } @@ -232,17 +242,30 @@ class ServerProvider extends BusyProvider { } } - String _getCPUTemp(String raw) { - final split = raw.split('\n'); - for (var item in split) { - if (item.contains('x86_pkg_temp') || item.contains('cpu_thermal')) { - return item.split(' ').last; - } + String _getCPUTemp(String type, String value) { + const noMatch = 'No such file or directory'; + // Not support to get CPU temperature + if (value.contains(noMatch) || + type.contains(noMatch) || + value.isEmpty || + type.isEmpty) { + return ''; } - return ''; + final split = type.split('\n'); + int idx = 0; + for (var item in split) { + if (item.contains(cpuTempReg)) { + break; + } + idx++; + } + return (int.parse(value.split('\n')[idx].trim()) / 1000) + .toStringAsFixed(1) + + '°C'; } - void _getCPU(ServerPrivateInfo spi, String raw, String temp) { + void _getCPU( + ServerPrivateInfo spi, String raw, String tempType, String tempValue) { final info = _servers.firstWhere((e) => e.info == spi); final List cpus = []; @@ -262,7 +285,7 @@ class ServerProvider extends BusyProvider { } if (cpus.isNotEmpty) { info.status.cpu2Status = - info.status.cpu2Status.update(cpus, _getCPUTemp(temp)); + info.status.cpu2Status.update(cpus, _getCPUTemp(tempType, tempValue)); } } diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index c71e1a33..2e557ead 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -2,9 +2,9 @@ class BuildData { static const String name = "ServerBox"; - static const int build = 113; + static const int build = 114; static const String engine = "Flutter 2.10.4 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision c860cba910 (3 weeks ago) • 2022-03-25 00:23:12 -0500\nEngine • revision 57d3bac3dd\nTools • Dart 2.16.2 • DevTools 2.9.2\n"; - static const String buildAt = "2022-04-15 19:46:15.224203"; - static const int modifications = 2; + static const String buildAt = "2022-04-15 20:20:29.860208"; + static const int modifications = 1; } diff --git a/lib/view/page/docker.dart b/lib/view/page/docker.dart index a1c2e9ff..68bc0949 100644 --- a/lib/view/page/docker.dart +++ b/lib/view/page/docker.dart @@ -66,7 +66,7 @@ class _DockerManagePageState extends State { Widget _buildMain() { return Consumer(builder: (_, docker, __) { - final running = docker.running; + final running = docker.items; if (docker.error != null && running == null) { return Center( child: Column( diff --git a/make.dart b/make.dart index 042de8e2..986aedda 100755 --- a/make.dart +++ b/make.dart @@ -5,6 +5,9 @@ import 'dart:convert'; import 'dart:io'; const appName = 'ServerBox'; +const buildDataFilePath = 'lib/data/res/build_data.dart'; +const xcarchivePath = 'build/ios/archive/Runner.xcarchive'; + const skslFileSuffix = '.sksl.json'; Future getGitCommitCount() async { @@ -64,8 +67,7 @@ Future updateBuildData() async { print('Updating BuildData...'); final data = await getBuildData(); print(jsonEncodeWithIndent(data)); - const path = 'lib/data/res/build_data.dart'; - await writeStaicConfigFile(data, 'BuildData', path); + await writeStaicConfigFile(data, 'BuildData', buildDataFilePath); } void dartFormat() { @@ -120,8 +122,8 @@ Future flutterBuild(String source, String target, bool isAndroid) async { } Future flutterBuildIOS() async { - await flutterBuild('./build/ios/archive/Runner.xcarchive', - './release/${appName}_build.xcarchive', false); + await flutterBuild( + xcarchivePath, './release/${appName}_build.xcarchive', false); } Future flutterBuildAndroid() async { @@ -149,10 +151,10 @@ void main(List args) async { final platform = args[1]; switch (platform) { case 'ios': - buildFunc.remove(flutterBuildIOS); + buildFunc.remove(flutterBuildAndroid); break; case 'android': - buildFunc.remove(flutterBuildAndroid); + buildFunc.remove(flutterBuildIOS); break; default: print('Unknown platform: $platform');