├── .gitignore
├── LICENSE
├── README.md
├── config
├── env.js
├── jest
│ ├── cssTransform.js
│ └── fileTransform.js
├── paths.js
├── polyfills.js
├── webpack.config.dev.js
├── webpack.config.prod.js
└── webpackDevServer.config.js
├── images
├── config.png
├── log.jpg
└── taillog.png
├── main.js
├── node
├── Service
│ ├── AgentServer.js
│ ├── CommonServer.js
│ ├── ConfigServer.js
│ ├── GroupServer.js
│ └── SSHServer.js
├── TermSSH.js
├── WebServer.js
└── WebSocketServer.js
├── package.json
├── public
├── favicon.ico
├── font-awesome-4.7.0
│ ├── HELP-US-OUT.txt
│ ├── css
│ │ ├── font-awesome.css
│ │ └── font-awesome.min.css
│ ├── fonts
│ │ ├── FontAwesome.otf
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.svg
│ │ ├── fontawesome-webfont.ttf
│ │ ├── fontawesome-webfont.woff
│ │ └── fontawesome-webfont.woff2
│ ├── less
│ │ ├── animated.less
│ │ ├── bordered-pulled.less
│ │ ├── core.less
│ │ ├── fixed-width.less
│ │ ├── font-awesome.less
│ │ ├── icons.less
│ │ ├── larger.less
│ │ ├── list.less
│ │ ├── mixins.less
│ │ ├── path.less
│ │ ├── rotated-flipped.less
│ │ ├── screen-reader.less
│ │ ├── stacked.less
│ │ └── variables.less
│ └── scss
│ │ ├── _animated.scss
│ │ ├── _bordered-pulled.scss
│ │ ├── _core.scss
│ │ ├── _fixed-width.scss
│ │ ├── _icons.scss
│ │ ├── _larger.scss
│ │ ├── _list.scss
│ │ ├── _mixins.scss
│ │ ├── _path.scss
│ │ ├── _rotated-flipped.scss
│ │ ├── _screen-reader.scss
│ │ ├── _stacked.scss
│ │ ├── _variables.scss
│ │ └── font-awesome.scss
├── index.html
├── logo.icns
├── logo.ico
├── logo.png
└── manifest.json
├── scripts
├── build.js
├── main.js
├── start.js
└── test.js
├── src
├── actions
│ ├── AjaxAction.js
│ ├── CommonAction.js
│ ├── LogAction.js
│ ├── LoginAction.js
│ ├── SettingAction.js
│ └── index.js
├── components
│ ├── Config
│ │ ├── Agent.js
│ │ ├── File.js
│ │ ├── SSH.js
│ │ ├── images
│ │ │ └── pig.png
│ │ ├── index.js
│ │ └── index.scss
│ ├── CopyRight
│ │ └── index.js
│ ├── Header
│ │ ├── Header2.js
│ │ ├── index.js
│ │ └── index.scss
│ ├── Right
│ │ ├── index.js
│ │ └── index.scss
│ ├── Setting
│ │ └── index.js
│ └── Source
│ │ ├── Agent.js
│ │ ├── Group.js
│ │ ├── SSH.js
│ │ ├── index.js
│ │ └── index.scss
├── configureStore.js
├── defaultData.js
├── fonts
│ ├── icomoon.eot
│ ├── icomoon.svg
│ ├── icomoon.ttf
│ ├── icomoon.woff
│ └── pomelo.ttf
├── images
│ ├── logo-no-circle.png
│ └── logo.png
├── index.js
├── index.less
├── index.scss
├── initReducer.js
├── logo.svg
├── reducers
│ └── index.js
├── routers
│ ├── Binding
│ │ └── index.js
│ ├── Config
│ │ ├── AgentList.js
│ │ ├── GroupList.js
│ │ ├── SSHList.js
│ │ ├── images
│ │ │ ├── pig1.png
│ │ │ ├── pig2.png
│ │ │ └── pig3.png
│ │ ├── index.js
│ │ └── index.scss
│ ├── Login
│ │ ├── Callback.js
│ │ ├── images
│ │ │ ├── logo-no-circle.png
│ │ │ ├── logo.png
│ │ │ ├── qq.png
│ │ │ └── weixin.png
│ │ ├── index.js
│ │ └── index.scss
│ ├── Logs
│ │ ├── Multi.js
│ │ ├── images
│ │ │ ├── pig1.png
│ │ │ ├── pig2.png
│ │ │ ├── pig3.png
│ │ │ └── pig4.png
│ │ ├── index.js
│ │ └── logs.scss
│ ├── NoMatch
│ │ ├── index.js
│ │ └── index.scss
│ ├── Pwd
│ │ ├── Reset.js
│ │ └── index.js
│ ├── Reg
│ │ ├── Activate.js
│ │ ├── RegAwait.js
│ │ └── index.js
│ ├── Settings
│ │ └── UserSetting.js
│ └── Term
│ │ ├── fullscreen.css
│ │ ├── images
│ │ ├── pig1.png
│ │ ├── pig2.png
│ │ ├── pig3.png
│ │ └── pig4.png
│ │ ├── index.js
│ │ ├── logs.scss
│ │ └── xterm.css
└── utils
│ ├── ApiList.js
│ ├── CheckList.js
│ ├── ajax.js
│ ├── crypto.js
│ └── url.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 |
11 | # misc
12 | .DS_Store
13 | .env.local
14 | .env.development.local
15 | .env.test.local
16 | .env.production.local
17 |
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 | .idea/
22 | /OutApp/
23 | /*.dmg
24 | /*.iml
25 | /node/.database/
26 | /build/
27 | /app/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 zhouli
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 简介
2 |
3 | [TailLog](http://taillog.cn/) 是一款实时日志查看监控工具。
4 |
5 | 
6 |
7 |
8 | 通过一次配置,即可便捷查看和监控本地或远程的日志信息(类似命令"tail",实时展示并跟踪日志信息)。
9 |
10 | 同时提供搜索,高亮等辅助等功能,方便快速定位异常,让你更专注于程序开发与维护。
11 | 
12 |
13 |
14 | ### 更多信息请查看
15 |
16 | [TailLog官网](http://taillog.cn/)
17 |
18 | [Github](https://github.com/djmpink/TailLog)
19 |
20 | [《独立开发一款产品是怎样的体验》](http://7player.cn/2018/06/20/%E7%8B%AC%E7%AB%8B%E5%BC%80%E5%8F%91%E4%B8%80%E6%AC%BE%E4%BA%A7%E5%93%81%E6%98%AF%E6%80%8E%E6%A0%B7%E7%9A%84%E4%BD%93%E9%AA%8C/)
21 |
22 | QQ交流群:455735429
23 |
24 | # 工程结构与原理
25 | 
26 |
27 | # 源码部署与运行
28 | ## 环境
29 | 如果你是一位专业的前端开发工程师,我想你已经具备了常用且必要的开发环境,可以直接跳过该部分,了解开发调试相关内容即可。
30 | 如果十分不幸遇到环境问题,可以尝试在这里找到答案。
31 |
32 | * 主要会涉及的工具与环境:
33 | * Node.js
34 | * python2
35 | * electron
36 |
37 | * 在开发或部署过程中,有一些注意事项或建议,可以更好的使用本工程:
38 | * npm加速 [可选,推荐]
39 |
40 | `npm config set registry=https://registry.npm.taobao.org`
41 |
42 | * Windows环境
43 |
44 | 因为win上没有C相关编译环境(linux系环境可忽略),而该工程需要安装node-sass,该模块需要编译环境
45 |
46 | 你可以通过以下命令设置node-sass的已编译好的文件[推荐],或者参考后文提到的编译环境部分来设置本地的编译环境
47 |
48 | `npm config set sass-binary-site=http://npm.taobao.org/mirrors/node-sass`
49 |
50 | * Mac环境
51 |
52 | 如果需要在Mac系统编译打包Windows系统的应用程序,则需要安装wine
53 |
54 | * 如果执行报node-sass相关错误,请确保:
55 | 1. 以上步骤的配置的sass-binary-site项是否正确
56 | 2. [不推荐]如果你不想通过配置sass-binary-site的方式,需要保证本地需要有相关编译环境: win上可以考虑使用
57 | [windows-build-tools](https://github.com/felixrieseberg/windows-build-tools)或安装VS 2015,但是这两者至少都是2G以上的空间占用,并且非常耗时
58 |
59 | * 或者你可以考虑使用`cnpm i`(如果没有安装cnpm,请先执行`npm i -g cnpm`),该命令不推荐在mac上执行,测试发现可能会出现一些意外问题
60 |
61 | * electron环境
62 | * 请全局安装electron:正常情况下应该直接执行`npm i -g electron`,但是因为国内环境问题,推荐下面的步骤(以win为例):
63 |
64 | 1. 使用[淘宝镜像](https://npm.taobao.org/mirrors/electron/)找到适合自己的版本:
65 |
66 | 下载[v2.0.2-win32-x64](https://npm.taobao.org/mirrors/electron/2.0.2/electron-v2.0.2-win32-x64.zip)即可
67 |
68 | 2. 解压文件夹并将electron.exe的目录设置到环境变量中:
69 | * 在C盘根目录下建立electron文件夹,将刚才下载的zip包解压后放置到该目录下
70 | * 找到其下的electron.exe对应的目录(本例中对应的目录是c:/electron/),将其加入到环境变量PATH中
71 | (对于不知道如何设置环境变量的同学请参考[百度经验](https://jingyan.baidu.com/article/8ebacdf02d3c2949f65cd5d0.html))
72 | * 设置完成后,你在任何新打开的cmd窗口中运行electron都能正常显示electron的窗口了,若不能,请检查前面是否设置不正确
73 |
74 | * 其他错误请提issue或者加入QQ群455735429
75 |
76 | ## 开发调试
77 | 如下命令均在项目根目录下执行。
78 | ### install
79 |
80 | npm i
81 |
82 | ### 编译
83 |
84 | npm run build
85 |
86 | ### 浏览器运行
87 |
88 | npm start
89 |
90 | ### 客户端(electron)运行
91 |
92 | 1. package.json中设置:`"DEV": true,`
93 | 2. 第一个命令行窗口执行:`npm start`
94 | 3. 第二个命令行窗口执行:`electron .` 或者直接执行`node scripts/main`
95 |
96 | ## 打包成客户端
97 | 1. package.json中设置:`"DEV": false,`
98 | 2. 命令行执行:`npm run build`
99 | 3. 打包
100 | * mac:
101 | 1. 执行 `npm run mac-pack`,该命令将在./app/下生成对应的文件夹和.app文件
102 | 第一次打包会有点慢,因为会下载对应的electron的包到用户目录下的.electron下,mac下是~/.electron
103 | 2. 执行`npm run mac-dmg` (如果没有安装electron-installer-dmg请先执行`npm i -g electron-installer-dmg`),该命令将在./app/下生成对应的.dmg文件
104 |
105 | * win:
106 | 1. 执行 `npm run win-pack`
107 | 2. 第一次打包会有点慢,因为会下载对应的electron的包到用户目录下的.electron下(win下是C:\Users\你的名字\.electron)
108 | mac上也可以直接执行`npm run mac-full`执行完以上的步骤2-3
109 |
110 | ## 其他注意事项
111 | * 如果要在mac上打包win,你需要参考[electron-packager Building Windows apps from non-Windows platforms](https://github.com/electron-userland/electron-packager#user-content-building-windows-apps-from-non-windows-platforms)章节,主要是需要安装wine
112 | * 如果在执行打包脚本的时候你卡在下载上,可以从[淘宝npm的electron镜像](https://npm.taobao.org/mirrors/electron/)上下载你需要的版本和其对应的SHASUMS256值,
113 | 放置到用户目录下的.electron下,win对应的目录是C:\Users\你的名字\.electron,mac下是~/.electron,win参考如下:
114 | 1. electron-v2.0.2-win32-x64.zip
115 | 2. SHASUMS256.txt-2.0.2 (没有其他后缀名,其内容参见[这里](https://npm.taobao.org/mirrors/electron/2.0.2/SHASUMS256.txt))
116 |
117 | ## 目录结构
118 | * app APP的生成目录(如果没有生成过,则不存在)
119 | * build 前端代码打包路径(如果没有生成过,则不存在)
120 | * config 前端项目配置目录
121 | * node 后端项目主目录
122 | * public 静态资源
123 | * scripts 脚本目录
124 | * src 前端主目录
125 | * components:组件
126 | * routers:路由,页面
127 | * Config:日志源配置页
128 | * Login:登录页
129 | * Logs:日志详情页
130 | * utils:公共方法
131 | * reducers
132 | * action
133 | * index.scss:通用样式
134 | * main.js 后端主入口
135 |
136 | ## Developers
137 |
138 | [七号球员](http://7player.cn/)
139 |
140 | [coolguy](https://www.hellocoolguy.com/)
141 |
142 |
143 |
--------------------------------------------------------------------------------
/config/env.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 | const path = require('path');
5 | const paths = require('./paths');
6 |
7 | // Make sure that including paths.js after env.js will read .env variables.
8 | delete require.cache[require.resolve('./paths')];
9 |
10 | const NODE_ENV = process.env.NODE_ENV;
11 | if (!NODE_ENV) {
12 | throw new Error(
13 | 'The NODE_ENV environment variable is required but was not specified.'
14 | );
15 | }
16 |
17 | // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
18 | var dotenvFiles = [
19 | `${paths.dotenv}.${NODE_ENV}.local`,
20 | `${paths.dotenv}.${NODE_ENV}`,
21 | // Don't include `.env.local` for `test` environment
22 | // since normally you expect tests to produce the same
23 | // results for everyone
24 | NODE_ENV !== 'test' && `${paths.dotenv}.local`,
25 | paths.dotenv,
26 | ].filter(Boolean);
27 |
28 | // Load environment variables from .env* files. Suppress warnings using silent
29 | // if this file is missing. dotenv will never modify any environment variables
30 | // that have already been set.
31 | // https://github.com/motdotla/dotenv
32 | dotenvFiles.forEach(dotenvFile => {
33 | if (fs.existsSync(dotenvFile)) {
34 | require('dotenv').config({
35 | path: dotenvFile,
36 | });
37 | }
38 | });
39 |
40 | // We support resolving modules according to `NODE_PATH`.
41 | // This lets you use absolute paths in imports inside large monorepos:
42 | // https://github.com/facebookincubator/create-react-app/issues/253.
43 | // It works similar to `NODE_PATH` in Node itself:
44 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
45 | // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
46 | // Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
47 | // https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
48 | // We also resolve them to make sure all tools using them work consistently.
49 | const appDirectory = fs.realpathSync(process.cwd());
50 | process.env.NODE_PATH = (process.env.NODE_PATH || '')
51 | .split(path.delimiter)
52 | .filter(folder => folder && !path.isAbsolute(folder))
53 | .map(folder => path.resolve(appDirectory, folder))
54 | .join(path.delimiter);
55 |
56 | // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
57 | // injected into the application via DefinePlugin in Webpack configuration.
58 | const REACT_APP = /^REACT_APP_/i;
59 |
60 | function getClientEnvironment(publicUrl) {
61 | const raw = Object.keys(process.env)
62 | .filter(key => REACT_APP.test(key))
63 | .reduce(
64 | (env, key) => {
65 | env[key] = process.env[key];
66 | return env;
67 | },
68 | {
69 | // Useful for determining whether we’re running in production mode.
70 | // Most importantly, it switches React into the correct mode.
71 | NODE_ENV: process.env.NODE_ENV || 'development',
72 | // Useful for resolving the correct path to static assets in `public`.
73 | // For example,
.
74 | // This should only be used as an escape hatch. Normally you would put
75 | // images into the `src` and `import` them in code to get their paths.
76 | PUBLIC_URL: publicUrl,
77 | }
78 | );
79 | // Stringify all values so we can feed into Webpack DefinePlugin
80 | const stringified = {
81 | 'process.env': Object.keys(raw).reduce((env, key) => {
82 | env[key] = JSON.stringify(raw[key]);
83 | return env;
84 | }, {}),
85 | };
86 |
87 | return {raw, stringified};
88 | }
89 |
90 | module.exports = getClientEnvironment;
91 |
--------------------------------------------------------------------------------
/config/jest/cssTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // This is a custom Jest transformer turning style imports into empty objects.
4 | // http://facebook.github.io/jest/docs/tutorial-webpack.html
5 |
6 | module.exports = {
7 | process() {
8 | return 'module.exports = {};';
9 | },
10 | getCacheKey() {
11 | // The output is always the same.
12 | return 'cssTransform';
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/config/jest/fileTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 |
5 | // This is a custom Jest transformer turning file imports into filenames.
6 | // http://facebook.github.io/jest/docs/tutorial-webpack.html
7 |
8 | module.exports = {
9 | process(src, filename) {
10 | return `module.exports = ${JSON.stringify(path.basename(filename))};`;
11 | },
12 | };
13 |
--------------------------------------------------------------------------------
/config/paths.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const fs = require('fs');
5 | const url = require('url');
6 |
7 | // Make sure any symlinks in the project folder are resolved:
8 | // https://github.com/facebookincubator/create-react-app/issues/637
9 | const appDirectory = fs.realpathSync(process.cwd());
10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
11 |
12 | const envPublicUrl = process.env.PUBLIC_URL;
13 |
14 | function ensureSlash(path, needsSlash) {
15 | const hasSlash = path.endsWith('/');
16 | if (hasSlash && !needsSlash) {
17 | return path.substr(path, path.length - 1);
18 | } else if (!hasSlash && needsSlash) {
19 | return `${path}/`;
20 | } else {
21 | return path;
22 | }
23 | }
24 |
25 | const getPublicUrl = appPackageJson =>
26 | envPublicUrl || require(appPackageJson).homepage;
27 |
28 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer
29 | // "public path" at which the app is served.
30 | // Webpack needs to know it to put the right