This commit is contained in:
lollipopkit
2023-08-28 19:26:17 +08:00
parent d06ffdacd0
commit d9c26e01f4
3 changed files with 130 additions and 51 deletions

View File

@@ -43,8 +43,7 @@ enum AppShellFuncType {
switch (this) {
case AppShellFuncType.status:
return '''
result=\$(uname 2>&1 | grep "Linux")
if [ "\$result" != "" ]; then
if [ "\$isLinux" != "" ]; then
\t${_statusCmds.join(_cmdDivider)}
else
\t${_bsdStatusCmd.join(_cmdDivider)}
@@ -59,23 +58,16 @@ else
fi''';
case AppShellFuncType.process:
return '''
# Try sequencially
# main Linux: `ps -aux`
# BSD: `ps -ax`
# alpine: `ps -o pid,user,time,args`
#
# If there is any error, try another one
result=\$(ps -aux 2>&1 | grep "ps: ")
if [ "\$result" = "" ]; then
ps -aux
if [ "\$isLinux" != "" ]; then
\tif [ "\$isBusybox" != "" ]; then
\t\tps w
\telse
\t\tps -aux
\tfi
else
result=\$(ps -ax 2>&1 | grep "ps: ")
if [ "\$result" = "" ]; then
ps -ax
else
ps -o pid,user,time,args
fi
fi''';
\tps -ax
fi
''';
}
}
@@ -201,6 +193,10 @@ final _shellCmd = """
export LANG=en_US.UTF-8
isLinux=\$(uname 2>&1 | grep "Linux")
# Link /bin/sh to busybox?
isBusybox=\$(ls -l /bin/sh | grep "busybox")
${AppShellFuncType.shellScript}
""";

View File

@@ -1,8 +1,40 @@
import 'package:logging/logging.dart';
import '../../../data/res/misc.dart';
final _logger = Logger('Proc');
class _ProcValIdxMap {
final int pid;
final int? user;
final int? cpu;
final int? mem;
final int? vsz;
final int? rss;
final int? tty;
final int? stat;
final int? start;
final int? time;
final int command;
_ProcValIdxMap({
required this.pid,
this.user,
this.cpu,
this.mem,
this.vsz,
this.rss,
this.tty,
this.stat,
this.start,
this.time,
required this.command,
});
}
/// Some field can be null due to incompatible format on `BSD` and `Alpine`
class Proc {
final String user;
final String? user;
final int pid;
final double? cpu;
final double? mem;
@@ -11,37 +43,37 @@ class Proc {
final String? tty;
final String? stat;
final String? start;
final String time;
final String? time;
final String command;
Proc({
required this.user,
this.user,
required this.pid,
required this.cpu,
required this.mem,
required this.vsz,
required this.rss,
required this.tty,
required this.stat,
required this.start,
required this.time,
this.cpu,
this.mem,
this.vsz,
this.rss,
this.tty,
this.stat,
this.start,
this.time,
required this.command,
});
factory Proc.parse(String raw) {
factory Proc.parse(String raw, _ProcValIdxMap map) {
final parts = raw.split(RegExp(r'\s+'));
return Proc(
user: parts[0],
pid: int.parse(parts[1]),
cpu: double.parse(parts[2]),
mem: double.parse(parts[3]),
vsz: parts[4],
rss: parts[5],
tty: parts[6],
stat: parts[7],
start: parts[8],
time: parts[9],
command: parts.sublist(10).join(' '),
user: map.user == null ? null : parts[map.user!],
pid: int.parse(parts[map.pid]),
cpu: map.cpu == null ? null : double.parse(parts[map.cpu!]),
mem: map.mem == null ? null : double.parse(parts[map.mem!]),
vsz: map.vsz == null ? null : parts[map.vsz!],
rss: map.rss == null ? null : parts[map.rss!],
tty: map.tty == null ? null : parts[map.tty!],
stat: map.stat == null ? null : parts[map.stat!],
start: map.start == null ? null : parts[map.start!],
time: map.time == null ? null : parts[map.time!],
command: parts.sublist(map.command).join(' '),
);
}
@@ -84,17 +116,38 @@ class PsResult {
factory PsResult.parse(String raw, {ProcSortMode sort = ProcSortMode.cpu}) {
final lines = raw.split('\n');
if (lines.isEmpty) return PsResult(procs: [], error: null);
final header = lines[0];
final parts = header.split(RegExp(r'\s+'));
parts.removeWhere((element) => element.isEmpty);
final map = _ProcValIdxMap(
pid: parts.indexOfOrNull('PID')!,
user: parts.indexOfOrNull('USER'),
cpu: parts.indexOfOrNull('%CPU'),
mem: parts.indexOfOrNull('%MEM'),
vsz: parts.indexOfOrNull('VSZ'),
rss: parts.indexOfOrNull('RSS'),
tty: parts.indexOfOrNull('TTY'),
stat: parts.indexOfOrNull('STAT'),
start: parts.indexOfOrNull('START'),
time: parts.indexOfOrNull('TIME'),
command: parts.indexOfOrNull('COMMAND') ?? parts.indexOfOrNull('CMD')!,
);
final procs = <Proc>[];
var err = '';
for (var i = 1; i < lines.length; i++) {
final line = lines[i];
if (line.isEmpty) continue;
try {
procs.add(Proc.parse(line));
} catch (e) {
procs.add(Proc.parse(line, map));
} catch (e, trace) {
err += '$line: $e\n';
_logger.warning(trace);
}
}
switch (sort) {
case ProcSortMode.cpu:
procs.sort((a, b) => b.cpu?.compareTo(a.cpu ?? 0) ?? 0);
@@ -106,7 +159,7 @@ class PsResult {
procs.sort((a, b) => a.pid.compareTo(b.pid));
break;
case ProcSortMode.user:
procs.sort((a, b) => a.user.compareTo(b.user));
procs.sort((a, b) => a.user?.compareTo(b.user ?? '') ?? 0);
break;
case ProcSortMode.name:
procs.sort((a, b) => a.binary.compareTo(b.binary));
@@ -124,3 +177,10 @@ enum ProcSortMode {
name,
;
}
extension _StrIndex on List<String> {
int? indexOfOrNull(String val) {
final idx = indexOf(val);
return idx == -1 ? null : idx;
}
}