使用MONO在MAC OS上开发——同步日志(一)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 原先打算再写点EXT.NET方面的,由于现在在玩Silverlight和Android,所以不打算写下去了。而且最近很忙,所以发帖也不会很及时。   好了,转入正题了:最近客户有个需求,要求写个小程序监控生产线上的苹果一体机的日志文件并上传到服务器。

  原先打算再写点EXT.NET方面的,由于现在在玩Silverlight和Android,所以不打算写下去了。而且最近很忙,所以发帖也不会很及时。

  好了,转入正题了:最近客户有个需求,要求写个小程序监控生产线上的苹果一体机的日志文件并上传到服务器。开始想使用Perl或者Python,但是时间不够(因为对这两门语言还不太熟悉),于是想试试MONO。MONO虽然没想象中好用,但是还算勉强能用。

  虽然MonoDevelop还可以,但是还是比较喜欢使用VS开发。于是在VS里面先编码。值得注意的是:

  1. 如果是开发Winform程序,界面用GTK重画吧。
  2. 如果是在VS里面开发,最好将所有的编码和注释都用英文。否则换其他系统时,可能会出现乱码。
  3. 编写时需注意MONO是否支持,否则就是白写。

接下来,开始编码。

1.读取配置文件

  习惯用XML,发现不支持System.Xml.Linq,亦不支持System.Xml,读取ini文件也麻烦,于是干脆读取文本文件好了。示例配置如下:

MonitoringDirectoryType:['Immediate','Cycle']

Path:['/Users/PRODUCTION/Public/FinalTest/LogsFolder','/Users/PRODUCTION/Public/FinalTest/LogsFolder']

TargetPath:['/Volumes/mes_data/FINALTEST/n81a/{Y}/{M}/{D}/FIN012','/Volumes/mes_data/FINALTEST/n81a/{Y}/{M}/{D}/FIN012']

IncludeSubdirectories:['FALSE','false']

Filter:['*.TXT','*.CSV']

BackupPath:['/Users/PRODUCTION/BACKUP/{Y}/{M}/{D}','/Users/PRODUCTION/BACKUP/{Y}/{M}/{D}']

BackupExpired:['2','2']

CycleMinutes:['','1440']

相关解析代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using MonitoringApp.Custom;
using System.Text.RegularExpressions;
using Gtk;
namespace MonitoringApp.Code.App
{
    public class Configuration
    {

        private static bool isLoadFirst = false;
        private static List<MyConfig> configLst;
        public static List<MyConfig> ConfigLst
        {
            get
            {
                if (configLst == null)
                {
                    try
                    {
                        if (!isLoadFirst)
                            return LoadFromInitParams();
                        else
                            return null;
                    }
                    catch (Exception ex)
                    {
                            LogManager.WriteErrorLog(ex);

                        return null;
                    }
                }
                return configLst;
            }
            set { configLst = value; }
        }

        /// <summary>
        /// Load Configuration file
        /// </summary>
        /// <returns></returns>
        private static List<MyConfig> LoadFromInitParams()
        {
            isLoadFirst = true;
            string _configPath = Path.Combine(Directory.GetCurrentDirectory(), "Configuration.txt");
            if (File.Exists(_configPath))
            {
                if (ConfigLst == null)
                    ConfigLst = new List<MyConfig>();
                else
                    return ConfigLst;
                using (StreamReader sr = new StreamReader(_configPath))
                {
                    int lineIndex = 1;
                    while (sr.Peek() > 0)
                    {
                        string str = sr.ReadLine().Trim();
                        if (str.Length == 0)
                            continue;
                        if (!str.Contains("[") || !str.Contains("]"))
                        {
                            LogManager.WriteErrorLog(string.Format("Config Error:'[' OR ']' Not Exist.At Line {0}.", lineIndex));
                            continue;
                        }
                        if (!str.Contains(":"))
                        {
                            LogManager.WriteErrorLog(string.Format("Config Error:':' Not Exist.At Line {0}.", lineIndex));
                            continue;
                        }
                        string[] names = str.Split(':');
                        str = str.Substring(str.IndexOf(':') + 1).Trim(']').Trim('[').Trim('\'');
                        string[] strConfigs = str.Split(',');
                        SetConfig(names, ConfigLst, strConfigs, lineIndex == 1);
                        lineIndex++;
                    }
                }
                return ConfigLst;
            }
            else
            {
                LogManager.WriteErrorLog(string.Format("can't find config file.Path:{0}.",_configPath));
                return null;
            }
        }
        /// <summary>
        /// Set Config
        /// </summary>
        /// <param name="name"></param>
        /// <param name="lst"></param>
        /// <param name="strConfigs"></param>
        private static void SetConfig(string[] name, List<MyConfig> lst, string[] strConfigs, bool isLineOne)
        {
            try
            {
                var mcConfig = (MonitoringConfigurations)Enum.Parse(typeof(MonitoringConfigurations), name[0], true);
                //Set Values
                for (int i = 0; i < strConfigs.Length; i++)
                {
                    string value = strConfigs[i].Trim('\'');
                    switch (mcConfig)
                    {
                        case MonitoringConfigurations.MonitoringDirectoryType:
                            {
                                #region MonitoringDirectoryType Defalut:immediate
                                switch (value.ToLower())
                                {
                                    case "immediate":
                                        {
                                            if (isLineOne)
                                            {
                                                MyConfig myConfig = new MyConfig();
                                                myConfig.MDType = MonitoringDirectoryType.Immediate;
                                                lst.Add(myConfig);
                                            }
                                            else
                                            {
                                                lst[i].MDType = MonitoringDirectoryType.Immediate;
                                            }
                                            break;
                                        }
                                    case "cycle":
                                        {
                                            if (isLineOne)
                                            {
                                                MyConfig myConfig = new MyConfig();
                                                myConfig.MDType = MonitoringDirectoryType.Cycle;
                                                lst.Add(myConfig);
                                            }
                                            else
                                            {
                                                lst[i].MDType = MonitoringDirectoryType.Cycle;
                                            }
                                            break;
                                        }
                                    default:
                                        {
                                            if (isLineOne)
                                            {
                                                MyConfig myConfig = new MyConfig();
                                                myConfig.MDType = MonitoringDirectoryType.Immediate;
                                                lst.Add(myConfig);
                                            }
                                            else
                                            {
                                                lst[i].MDType = MonitoringDirectoryType.Immediate;
                                            }
                                            break;
                                        }
                                }
                                #endregion
                                break;
                            }
                        case MonitoringConfigurations.Path:
                            #region Path
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.Path = value;
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].Path = value;
                            }
                            #endregion
                            break;
                        case MonitoringConfigurations.IncludeSubdirectories:
                            #region IncludeSubdirectories
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.IncludeSubdirectories = Convert.ToBoolean(value);
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].IncludeSubdirectories = Convert.ToBoolean(value);
                            }
                            #endregion
                            break;
                        case MonitoringConfigurations.Filter:
                            #region Filter
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.Filter = value;
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].Filter = value;
                            }
                            break;
                            #endregion
                        case MonitoringConfigurations.BackupPath:
                            #region BackupPath
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.BackupPath = value;
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].BackupPath = value;
                            }
                            #endregion
                            break;
                        case MonitoringConfigurations.TargetPath:
                            #region TargetPath
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.TargetPath = value;
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].TargetPath = value;
                            }
                            #endregion
                            break;
                        case MonitoringConfigurations.BackupExpired:
                            #region BackupExpired  Unit:days  Default:30
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.BackupExpired = Convert.ToInt32(value.Length == 0 ? "30" : value);
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].BackupExpired = Convert.ToInt32(value.Length == 0 ? "30" : value);
                            }
                            #endregion
                            break;
                        case MonitoringConfigurations.CycleMinutes:
                            #region CycleMinutes  Unit:Minute  Default:60
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.CycleMinutes = Convert.ToInt32(value.Length == 0 ? "60" : value);
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].CycleMinutes = Convert.ToInt32(value.Length == 0 ? "60" : value);
                            }
                            #endregion
                            break;
                        default:
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.WriteErrorLog(ex);
            }


        }

    }
}

 

 

值得注意的是:

  1. 这里是按行读取的。从读取配置来看,可以看出,是支持多个配置项的。
  2. 如果出错,会记录日志。
  3. 和客户讲解如何配置是一件麻烦的事情。相关配置解释如下:
	MonitoringDirectoryType:目录类型,仅支持两个值(Immediate、Cycle)。Immediate表示即时监控(默认值),Cycle表示周期监控。	
	Path:监控目录路径。必须是存在的路径。
	TargetPath:目标目录路径。可以是远程目录路径。不能使用SMB路径,而应该是用如“/Volumes/mes_data/n81a”的类型。
	IncludeSubdirectories:是否涵盖子目录。
	Filter:过滤字符串。如“*”表示监控所有文件,“*.txt”表示监控所有的文本文件。
	BackupPath:备份路径。
	BackupExpired:备份过期时间。单位是天。必须为整数。默认值30天。
	CycleMinutes:周期循环时间。单位是分。 必须为整数。默认值60分钟。

 

然后针对配置写个说明文档,这样客户就会配置了。

2)记录日志

程序运行起来总不可避免的会遇到各种问题,记录日志就不可避免了。相关代码如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Gtk;

namespace MonitoringApp.Code.App
{
    public class LogManager
    {
        public static object obj = new object();
        static LogManager()
        {
        }
        #region Fields and Properties
        private static string _logPath = string.Empty;
        public static string LogPath
        {
            get
            {
                lock (obj)
                {
                    if (_logPath == string.Empty)
                    {
                        var _logStr = string.Format("{0}/log/{1}/{2}", Path.Combine(Directory.GetCurrentDirectory(), "Data"), DateTime.Now.ToString("yyyy-MM"), DateTime.Now.Day);
                        if (!System.IO.Directory.Exists(_logStr))
                            System.IO.Directory.CreateDirectory(_logStr);
                        return string.Format("{0}/", _logStr);
                    }
                    return _logPath;
                }
            }
            set { _logPath = value; }
        }
        private static string _logFielPrefix = string.Empty;
        public static string LogFielPrefix
        {
            get { return _logFielPrefix; }
            set { _logFielPrefix = value; }
        }
        #endregion

        #region Log

        public static void WriteLog(string logFile, string msg)
        {
            try
            {
                lock (obj)
                {
                    var _sb = new System.Text.StringBuilder();
                    _sb.Append(LogPath).Append(LogFielPrefix).Append(logFile).Append(".Log");
                    using (var _sw = System.IO.File.AppendText(_sb.ToString()))
                    {
                        _sw.WriteLine("==============================={0}===============================", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        _sw.WriteLine(msg);
                        _sw.Flush();
                        _sw.Close();
                        Console.WriteLine(msg);

                    }
                }
            }
            catch
            { }
        }

        public static void WriteLog(LogFile logFile, string msg)
        {
            WriteLog(logFile.ToString(), msg);
        }
        public static void WriteTraceLog(string msg)
        {
            Console.WriteLine(msg);
        }

        public static void WriteErrorLog(string msg)
        {
            WriteLog(LogFile.Error, msg);
        }
        public static void WriteErrorLog(Exception ex)
        {
            var _sbError = new StringBuilder();
            _sbError.Append("[Message]").Append(ex.Message);
            _sbError.Append("\r\n[TargetSite]").Append(ex.TargetSite);
            _sbError.Append("\r\n[StackTrace]").Append(ex.StackTrace);
            _sbError.Append("\r\n[Source]").Append(ex.Source);
            foreach (var _item in ex.Data.Keys)
            {
                _sbError.Append("\r\n[").Append(_item).Append("]").Append(ex.Data[_item]);
            }
            if (ex.InnerException != null && ex.InnerException.Message != ex.Message)
            {
                _sbError.AppendLine("____________________________________________________________________________________");
                _sbError.Append("[Message]").Append(ex.InnerException.Message);
                _sbError.Append("\r\n[TargetSite]").Append(ex.InnerException.TargetSite);
                _sbError.Append("\r\n[StackTrace]").Append(ex.InnerException.StackTrace);
                _sbError.Append("\r\n[Source]").Append(ex.InnerException.Source);
                _sbError.AppendLine("____________________________________________________________________________________");
            }
            WriteLog(LogFile.Error, _sbError.ToString());
        }
        public static void WriteWarningLog(string msg)
        {
            WriteLog(LogFile.Warning, msg);
        }
        #endregion
    }

    public enum LogFile
    {
        Trace,
        Warning,
        Error,
        SQL,
        System
    }
}

值得注意的是“Directory.GetCurrentDirectory()可以获取到当前用户的个人目录,至于获取到程序当前目录路径,Winform的那一套不管用(如果哪位朋友找到了适合的方法,请留言)。苹果系统和Window系统差别太大,从没玩过苹果系统,刚开始玩还挺不习惯的。

接下来,讲述如何监控目录以及定时备份,最后讲述如何发布部署。发布部署才是最重要的一环。不上生产线,就不知道会有什么问题。当初以为这个小程序,一天就能搞定,结果中秋3天都废了。还好万幸搞定。时间关系,就此打住。

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
7月前
|
人工智能 搜索推荐 API
🚀 2小时极速开发!基于DeepSeek+智体OS的AI社交「头榜」震撼上线!
基于DeepSeek大模型与DTNS协议的革命性AI社交平台「头榜」震撼上线!仅需2小时极速开发,即可构建完整社交功能模块。平台具备智能社交网络、AI Agent生态、Prompt市场、AIGC创作等六大核心优势,支持低代码部署与个性化定制。开发者可快速接入DeepSeek API,体验去中心化架构与数据自主权。官网:[dtns.top](https://dtns.top),立即开启你的AI社交帝国!#AI社交 #DeepSeek #DTNS协议
239 4
|
10月前
|
存储 人工智能 JavaScript
Harmony OS开发-ArkTS三
本文介绍了ArkTS的基础语法,包括常量、命名规则、数组及其常用函数,以及函数的定义与使用,涵盖匿名函数和箭头函数的区别。通过具体示例,帮助读者快速掌握ArkTS编程技巧,踏上Harmony OS开发之旅。君志所向,一往无前!
546 1
Harmony OS开发-ArkTS三
|
8月前
|
Web App开发 安全 iOS开发
基于PyCharm与Mac系统的Chrome历史记录清理工具开发实战
《基于PyCharm与Mac系统的Chrome历史记录清理工具开发实战》详细解析了如何在macOS下通过Python脚本自动化清理Chrome浏览器的历史记录。文章以`clear_chrome_history.py`为例,结合PyCharm开发环境,深入讲解技术实现。内容涵盖进程检测、文件清理、虚拟环境配置及断点调试技巧,并提供安全增强与跨平台适配建议。该工具不仅保障个人隐私,还适用于自动化运维场景,具备较高实用价值。
222 0
|
11月前
|
存储 人工智能 JavaScript
Harmony OS开发-ArkTS语言速成二
本文介绍了ArkTS基础语法,包括三种基本数据类型(string、number、boolean)和变量的使用。重点讲解了let、const和var的区别,涵盖作用域、变量提升、重新赋值及初始化等方面。期待与你共同进步!
516 47
Harmony OS开发-ArkTS语言速成二
|
10月前
|
存储 人工智能 编译器
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
580 10
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
|
10月前
|
前端开发 JavaScript 开发工具
【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
608 5
【04】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-正确安装鸿蒙SDK-结构目录介绍-路由介绍-帧动画(ohos.animator)书写介绍-能够正常使用依赖库等-ArkUI基础组件介绍-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
|
9月前
|
缓存 Java 编译器
|
10月前
|
安全 前端开发 开发工具
【01】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-优雅草卓伊凡拟开发一个一站式家政服务平台-前期筹备-暂定取名斑马家政软件系统-本项目前端开源-服务端采用优雅草蜻蜓Z系统-搭配ruoyi框架admin后台-全过程实战项目分享-从零开发到上线
【01】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-优雅草卓伊凡拟开发一个一站式家政服务平台-前期筹备-暂定取名斑马家政软件系统-本项目前端开源-服务端采用优雅草蜻蜓Z系统-搭配ruoyi框架admin后台-全过程实战项目分享-从零开发到上线
480 5
【01】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-优雅草卓伊凡拟开发一个一站式家政服务平台-前期筹备-暂定取名斑马家政软件系统-本项目前端开源-服务端采用优雅草蜻蜓Z系统-搭配ruoyi框架admin后台-全过程实战项目分享-从零开发到上线
|
10月前
|
JavaScript 编译器 开发工具
【02】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-准备工具安装-编译器DevEco Studio安装-arkts编程语言认识-编译器devco-鸿蒙SDK安装-模拟器环境调试-hyper虚拟化开启-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
【02】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-准备工具安装-编译器DevEco Studio安装-arkts编程语言认识-编译器devco-鸿蒙SDK安装-模拟器环境调试-hyper虚拟化开启-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
520 2
【02】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-项目开发实战-准备工具安装-编译器DevEco Studio安装-arkts编程语言认识-编译器devco-鸿蒙SDK安装-模拟器环境调试-hyper虚拟化开启-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
|
12月前
|
开发框架 JavaScript 前端开发
Harmony OS开发-ArkT语言速成一
本文介绍ArkTS语言,它是鸿蒙生态的应用开发语言,基于TypeScript,具有静态类型检查、声明式UI、组件化架构、响应式编程等特性,支持跨平台开发和高效性能优化。ArkTS通过强化静态检查和分析,提升代码健壮性和运行性能,适用于Web、移动端和桌面端应用开发。关注我,带你轻松掌握HarmonyOS开发。
520 5
Harmony OS开发-ArkT语言速成一

热门文章

最新文章

推荐镜像

更多