使用SVN钩子自动更新服务器的一些坑
程序员文章站
2022-06-11 10:06:57
...
博客重建工作一切从0开始,万事开头难,期间很多想法想来简单,但付诸实践却很是棘手。
服务器是Win2012 R2 + IIS7
我所使用的SVN服务商是免费的SVNBucket,它提供了一个很给力的功能,SVN钩子,意思就是每次Commit后,自动访问这个网页,达到服务器自动同步的目的,也就不用再沙雕的在服务器上每1分钟自动更新,浪费本就可怜的内存。
最开始的想法是写个batch,然后控制器触发CMD调用。
批处理内容:
svn update D:\Web1
svn update D:\Web2
控制器内容:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Diagnostics;
using System.IO;
namespace Web.Controllers
{
public class TestController : Controller
{
public String Update()
{
WindowsTools t = new WindowsTools();
var str = t.RunCmd2(@"D:\SVNupdate.bat").ToString();
return str;
}
}
public class WindowsTools
{
/// <summary>
/// 运行cmd命令
/// 不显示命令窗口
/// </summary>
/// <param name="cmdExe">指定应用程序的完整路径</param>
public string RunCmd2(string cmdExe)
{
try
{
using (Process myPro = new Process())
{
myPro.StartInfo.FileName = "cmd.exe";
myPro.StartInfo.UseShellExecute = false;
myPro.StartInfo.RedirectStandardInput = true;
myPro.StartInfo.RedirectStandardOutput = true;
myPro.StartInfo.RedirectStandardError = true;
myPro.StartInfo.CreateNoWindow = true;
myPro.Start();
myPro.StandardInput.WriteLine(cmdExe);
myPro.StandardInput.AutoFlush = true;
myPro.StandardInput.WriteLine("exit");
string outStr = myPro.StandardOutput.ReadToEnd();
myPro.Close();
return outStr;
}
}catch(Exception e)
{
return e.Message;
}
}
}
}
看起来一切都那么美好,但是,线上环境的cmd调用始终有问题,就是无法触发。
控制器返回结果:
Microsoft Windows [版本 10.0.17763.775]
(c) 2018 Microsoft Corporation。保留所有权利。
C:\\windows\\sytstem32\\inetsrv>D:\\SVNupdate.bat.bat
C:\\windows\\sytstem32\\inetsrv>svn update D:\\Web1
C:\\windows\\sytstem32\\inetsrv>svn update D:\\Web2
C:\\windows\\sytstem32\\inetsrv>exit
执行完【svn update】后竟是一片空白。。。。。
无奈各种资料查阅,猜测原因是权限问题。
于是查阅到了一篇关于解决权限的IIS设置解决方案:https://www.cnblogs.com/yuyuko/p/10697856.html
设置后再加服务器重启,还是不行,包括文件上给足权限,cmd给足权限,快捷方式扔windows32目录, 各种折腾后,我放弃了。。。
实在是太无奈了,为了体验下SVN钩子神奇的功能,只能逼我大招了。。。
我想到了另一个解决方法。进程间通信。。。
【终极方案】
然后另写一个控制器程序,挂在服务器上,把快捷方式扔进
【C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp】这个目录(开机启动项目录),然后最小化挂着就行了。
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Threading;
namespace updatesvn
{
class Program
{
static void Main(string[] args)
{
Thread receiveDataThread = new Thread(ReceiveDataFromClient);
receiveDataThread.IsBackground = true;
receiveDataThread.Start();
receiveDataThread.Join();
}
private static NamedPipeServerStream _pipeServer;
private static void ReceiveDataFromClient()
{
while (true)
{
try
{
_pipeServer = new NamedPipeServerStream("svnPipe", PipeDirection.InOut, 2);
_pipeServer.WaitForConnection(); //Waiting
StreamReader sr = new StreamReader(_pipeServer);
string recData = sr.ReadLine();
if (recData == "update"){
System.Diagnostics.Process.Start(@"D:\SVNupdate.bat");
}else if(recData == "Exit"){
Console.WriteLine("Pipe Exit.");
Process.GetCurrentProcess().Kill();
}
Console.WriteLine(recData + DateTime.Now.ToString());
Thread.Sleep(1000);
sr.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
}
控制器代码:
using System;
using System.Web.Mvc;
using Web.Tools;
namespace Web.Controllers
{
public class SVNUpdateController : Controller
{
public String Update()
{
var b = WindowsTools.SendUpdate().ToString();
return b+DateTime.Now.ToString();
}
}
}
另附一个工具类
using System.IO;
using System.IO.Pipes;
using System.Security.Principal;
namespace Web.Tools
{
public class WindowsTools
{
private static NamedPipeClientStream _pipeClient;
public static bool SendData(string cmd)
{
try
{
_pipeClient = null;
_pipeClient = new NamedPipeClientStream(".", "svnPipe", PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.Impersonation);
_pipeClient.Connect();
StreamWriter sw = new StreamWriter(_pipeClient);
sw.WriteLine(cmd);
sw.Flush();
sw.Close();
return true;
}
catch {
return false;
}
}
public static bool SendUpdate() {
return SendData("update");
}
}
}
大功告成。SVN钩子测试成功。如果以后有更好的方案,我再回来补充上。