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

  原先打算再写点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文件也麻烦,于是干脆读取文本文件好了。示例配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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']

相关解析代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
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. 和客户讲解如何配置是一件麻烦的事情。相关配置解释如下:
1
2
3
4
5
6
7
8
MonitoringDirectoryType:目录类型,仅支持两个值(Immediate、Cycle)。Immediate表示即时监控(默认值),Cycle表示周期监控。   
Path:监控目录路径。必须是存在的路径。
TargetPath:目标目录路径。可以是远程目录路径。不能使用SMB路径,而应该是用如“/Volumes/mes_data/n81a”的类型。
IncludeSubdirectories:是否涵盖子目录。
Filter:过滤字符串。如“*”表示监控所有文件,“*.txt”表示监控所有的文本文件。
BackupPath:备份路径。
BackupExpired:备份过期时间。单位是天。必须为整数。默认值30天。
CycleMinutes:周期循环时间。单位是分。 必须为整数。默认值60分钟。

 

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

2)记录日志

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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天都废了。还好万幸搞定。时间关系,就此打住。

posted @   雪雁  阅读(2811)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示