如果你想在你的程序中解决它,你可以遍历 System.Diagnostics.Process.GetProcesses 中的所有进程并检查是否有任何进程可执行路径以你的文件名结尾。
[System.STAThread]
static void Main(string[] args)
{
foreach (System.Diagnostics.Process p in System.Diagnostics.Process.GetProcesses())
{
if (p.MainModule.FileName.EndsWith("bla.exe", System.StringComparison.CurrentCultureIgnoreCase))
return;
}
[...]
}
否则,让脚本在 /var/run 中设置一个值并检查该文件是否存在。如果您的程序以任何方式退出,该文件将被删除。
另外,解决长时间运行的问题。
程序通常不应该花费那么长时间。
在我看来你做错了什么,除非你确实在处理几 GB 的数据。
如果 MainModule 返回 dotnet,您还可以读取链接 proc/pid/exe/(Linux 或 BSD)或 /proc/self/exe(仅限 Linux)
int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
System.Text.StringBuilder sb = new System.Text.StringBuilder(System.Environment.SystemPageSize);
int ret = Mono.Unix.Native.Syscall.readlink($"/proc/{pid}/exe", sb);
string res = sb.ToString();
System.Console.WriteLine(res);
或者,如果这也只产生 dotnet,您可以读取命令行参数(/proc/pid/cmdline - 仅限 linux):
public static byte[] ReadReallyAllBytes(string filename)
{
byte[] retValue = null;
using (System.IO.FileStream fs = System.IO.File.OpenRead(filename))
{
byte[] buffer = new byte[System.Environment.SystemPageSize];
List<byte> byteList = new List<byte>();
int ct = 0;
while ((ct = fs.Read(buffer, 0, buffer.Length)) > 0)
{
for (int i = 0; i < ct; ++i)
{
byteList.Add(buffer[i]);
}
}
buffer = null;
retValue = byteList.ToArray();
byteList.Clear();
byteList = null;
}
return retValue;
}
public static List<string> GetCmdLineArgs(int pid)
{
List<string> ls = new List<string>();
byte[] buffer = ReadReallyAllBytes($"/proc/{pid}/cmdline");
int last = 0;
for (int i = 0; i < buffer.Length; ++i)
{
if (buffer[i] == 0)
{
string arg = System.Text.Encoding.UTF8.GetString(buffer, last, i-last);
last = i + 1;
ls.Add(arg);
} // End if (buffer[i] == 0)
} // Next i
// System.Console.WriteLine(ls);
return ls;
}
现在如果 MainModule 是 dotnet,请检查命令行参数列表是否包含您的 dll/exe。
此外,如果您进行发布构建(独立 - 无共享框架),那么它应该与 MainModule 一起使用。