dotnet core 网站一个痛点是不会自动重启。
ftp上传更新后需要查找原先的进程,kill掉那个进程,然后启动。
想想原先dotnet ftp直接覆盖就ok了,不用启动一个shell,登陆,ps -aux|grep dotnet ,找到那个进程, kill 进程号,然后 到 网站目录下,nohup dotnet xxx.dll & .
我想,可以写个小程序,进行这几步操作。
但有个问题,怎么知道文件改动了。想到有个FileSystemWatcher的类,能够解决这个问题。
最初是考虑监视 .dll 文件 ,后来想,如果有多个 .dll 文件,一个替换就启动一次,那不是需要启动多次吗?后来考虑延时启动,比如 10秒后,.dll文件没有被替换了,就重启,但延时的时间不好控制。后来想,是不是考虑复杂了。直接设置一个文件,如果文件存在就重启,监视程序重启后把那个文件删除不就可以了。web发布的时候把那个文件设为总是复制。ftp上传的时候最后上传这个文件就可以了。
写好代码,测试。通过。
Program.cs
using System;
using System.IO;
using System.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using System.Diagnostics;
namespace dog
{
class Program
{
static void read_config()
{
var builder = new ConfigurationBuilder();
builder.AddJsonFile("dog.json");
IConfigurationRoot config = builder.Build();
file_path = config["file_path"];
command = config["command"];
argument = config["argument"];
find = config["find"];
debug_file = config["debug_file"];
command2 = config["command2"];
argument2 = config["argument2"];
watch_create_file = config["watch_create_file"];
}
public static string file_path = "";
public static string command = "";
public static string argument = "";
public static string find = "";
public static string debug_file = "";
public static string command2 = "";
public static string argument2 = "";
public static string watch_create_file = "";
static void restart()
{
string pid = "";
var psi = new System.Diagnostics.ProcessStartInfo(command, argument);
psi.RedirectStandardOutput = true;
using (var process = System.Diagnostics.Process.Start(psi))
{
var output = process.StandardOutput.ReadToEnd();
string[] lines = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
foreach(string aLine in lines)
{
if (aLine.IndexOf(find) != -1)
{
string[] lines2 = aLine.Split(new string[]{" "},StringSplitOptions.RemoveEmptyEntries);
pid = lines2[1];
}
}
}
if(pid!=""){
command = "kill";
argument = pid;
psi = new System.Diagnostics.ProcessStartInfo(command, argument);
psi.RedirectStandardOutput = true;
using (var process = System.Diagnostics.Process.Start(psi))
{
}
psi = new System.Diagnostics.ProcessStartInfo(command2, argument2);
psi.RedirectStandardOutput = true;
using (var process = System.Diagnostics.Process.Start(psi))
{
}
}
}
static void Main(string[] args)
{
read_config();
WatcherStrat(file_path, "*.prop");
Console.ReadKey();
}
private static void WatcherStrat(string path, string filter)
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = path;
watcher.Filter = filter;
watcher.Changed += new FileSystemEventHandler(OnProcess);
watcher.Created += new FileSystemEventHandler(OnProcess);
watcher.Deleted += new FileSystemEventHandler(OnProcess);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
watcher.EnableRaisingEvents = true;
watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess
| NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;
watcher.IncludeSubdirectories = true;
}
private static void OnProcess(object source, FileSystemEventArgs e)
{
if (e.ChangeType == WatcherChangeTypes.Created)
{
OnCreated(source, e);
}
else if (e.ChangeType == WatcherChangeTypes.Changed)
{
OnChanged(source, e);
}
else if (e.ChangeType == WatcherChangeTypes.Deleted)
{
OnDeleted(source, e);
}
}
private static void OnCreated(object source, FileSystemEventArgs e)
{
Console.WriteLine("文件新建事件处理逻辑 {0} {1} {2}", e.ChangeType, e.FullPath, e.Name);
string file_name = System.IO.Path.GetFileName(e.FullPath);
if(file_name==watch_create_file){
restart();
System.IO.File.Delete(e.FullPath);
}
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
Console.WriteLine("文件改变事件处理逻辑{0} {1} {2}", e.ChangeType, e.FullPath, e.Name);
}
private static void OnDeleted(object source, FileSystemEventArgs e)
{
Console.WriteLine("文件删除事件处理逻辑{0} {1} {2}", e.ChangeType, e.FullPath, e.Name);
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
Console.WriteLine("文件重命名事件处理逻辑{0} {1} {2}", e.ChangeType, e.FullPath, e.Name);
}
}
}
dog.json
{
"file_path": "/data/wwwroot/xxxxxxx/",
"command": "ps",
"argument": " -aux",
"find": "dotnet core_xxxxx.dll",
"debug_file": "/root/dog/debug.txt",
"command2":"nohup",
"argument2":"/etc/init.d/dotnet_start.sh &",
"watch_create_file":"restart.prop"
}