mgic

mgic 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

mgic 关注了专栏 · 7月15日

SOCKSTACK技术分享

SOCKSTACK技术分享

关注 5

mgic 关注了问题 · 3月15日

求助 ubuntu oh-my-zsh主题agnoster 符号异常

Snipaste_2020-03-12_23-31-58.png

agnoster主题配置

  • .zshrc主题更改
  • 字体安装: `sudo apt-get install fonts-powerline`

仍异常

关注 1 回答 0

mgic 提出了问题 · 3月13日

求助 ubuntu oh-my-zsh主题agnoster 符号异常

Snipaste_2020-03-12_23-31-58.png

agnoster主题配置

  • .zshrc主题更改
  • 字体安装: `sudo apt-get install fonts-powerline`

仍异常

关注 1 回答 0

mgic 提出了问题 · 3月13日

求助 ubuntu oh-my-zsh主题agnoster 符号异常

Snipaste_2020-03-12_23-31-58.png

agnoster主题配置

  • .zshrc主题更改
  • 字体安装: `sudo apt-get install fonts-powerline`

仍异常

关注 1 回答 0

mgic 赞了文章 · 2019-12-30

vscode + vagrant + frp 远程开发环境

文章讲什么

本文主要讲,我是如何循序渐进地搭建一个远程开发环境,最后实现的效果是:在公司使用mac进行办公,然后通过frp转发家里台式机的端口,RDP到家里的台式windows,并且SSH直连到windows中使用vagrant管理的一套虚拟机环境,其使用体验就像是拥有了超高配置的云服务器一样。使用mac安装的 vs code 进行开发的时候,使用remote develop扩展包,直连windows开的高配ubuntu虚拟机,从此再也不用担心环境和性能的问题了。(remote develop扩展包,可以让你使用远程主机或者docker中的环境进行开发,本机的vs code此时就像是个浏览器一样,十分的方便)

备注

本文不会贴具体的代码,只是讲一下我整个的过程和思路,因为我觉得这才是最重要的东西。

背景

最近新入职了一家公司,名字就不说了。公司对保密的要求十分严格,对内外网进行了分离,并且只配发了台式机,8g、i5、机械硬盘的配置。用内网就不能访问外网,也就是一些涉及到在线安装的东西全都死翘翘了(比如咱们各种IDE在线安装插件,或者其他开发工具涉及到联网的部分)。用外网的话,文件就无法保存,相当于是开了一个还原卡系统一样的东西,所以想安装软件的唯一途径就是U盘拷贝,或者使用外网后将文件手动导出,然后在内网模式进行安装(说实话作为一个喜欢折腾的程序员,我吐了)。

于是我一直都是使用的我的mac进行工作,但是性能实在有些顶不住(内存定制的是16G),工作内容经常需要集群环境,而且编译工作很重,我只能在mac上开一堆虚拟机进行模拟,经常就风扇狂响,键盘烫手。于是我就想用远程控制我家里的台式机(i7 9700k,1T的三星Nvme固态、40G内存),将台式当作额外的云服务器来用。诞生了这个想法后,我就开始了折腾之旅。。。

如何快速搭建开发环境(windows + mac)

其实吧,由于工作内容的关系,我需要一套很重的开发环境(经常启停一套集群进行测试,各种中间件和工具一大堆),所以在使用mac的时候就折腾了很久的开发环境的搭建的问题。虽然mac号称能跑linux上的很多东西,但是实际上使用的时候,是有很多不兼容的地方的,最后依然需要真正的linux系统来进行开发,不然解决兼容性的问题就把自己烦死了(还是工作内容的原因,我没办法只用docker就组一套环境)。下面就是我折腾开发环境的过程

阶段1:mac开虚拟机

这个阶段就是很朴实的想法,哈哈。在mac装了vmware fusion,然后就是一顿熟悉的操作,安装虚拟机balabala的,这个事儿估计大家都干过,详细过程就不用多说了。

这种方式问题就很大,首先就是安装的过程,我需要手动一步一步的点击下一步,然后改虚拟机的硬件配置啥的,总之是一个经常重复而且效率低下的过程。用了几天之后我就摒弃这种方案了。

阶段2:mac使用vagrant

在阶段一之后,我找了一些资料,然后找到了vagrant。使用过这个工具之后就感觉,这才是程序员使用虚拟机的时候应该有的方式。vagrant可以使用现在主流的VM软件,比如vmware、virtualBox等,对虚拟机进行管理,也就是说,使用vagrant在命令行中开启、关闭、配置虚拟机,并且他还有一个云端的仓库,就像是dockerhub一样的东西,专门用来下载系统镜像。使用vagrant之后,你就可以通过类似于写一个DockerFile的方式,写一个VagrantFile来定义一组虚拟机(一个VagrantFile可以定义无数个虚拟机),然后根据需要,随时开启或者销毁不同的虚拟机实例,一下子就把你从手工方式启停虚拟机里解放了出来。

于是我就折腾了两天,写了一个自己满意的VagrantFile,定义了一套虚拟机环境,达到的效果就是:免密SSH、创建时自动安装了我需要的环境、hosts文件共享,静态IP,自动加入docker swarm集群。到了这个阶段之后,其实环境的问题已经基本上解决了,但是性能问题依然还在,我mac上本身也已经有一堆东西了,内存和CPU余量其实并不多,基本上开的虚拟机性能都比较垃圾,而且散热会比较吃力,所以实际使用起来体验并不好。

阶段3:windows使用vagrant + teamviewer 远程控制

mac使用vagrant已经很明显已经是个比较有效的方案了,唯一的问题就是性能不足。所以我就想到了家里的顶配台式机。于是用台式机也安装了vagrant,但是此时遇到了一个问题。

vagrant实际上是要依赖具体的虚拟机软件的,它本身其实只是一个命令行工具,负责管理而不是负责创建虚拟机。可以这么想:各个虚拟机软件其实都有命令行接口可以进行虚拟机的管理,但是各种虚拟机软件的接口使用方式都不同,而且十分复杂,所以vagrant就在各个虚拟机软件的接口上做了一层封装,我们使用vagrant进行虚拟机的管理,而vagrant则在底层去调用具体的虚拟机软件进行虚拟机的创建和管理等工作。

遇到的问题

我遇到的问题就是:win10里安装docker的时候,必须要打开hyper-v,实际上win10里的docker是运行在hyper-v模拟出来的一个linux虚拟机中的。所以要使用docker就必须打开hyper-v,但是hyper-v有一个致命的缺点,就是不与其他虚拟机软件兼容,也就是说开了hyper-v就没法使用virtualBox和VMware。而且开了hyper-v之后,win10本身其实也是运行在hyper-v里的(可以理解为:其实只有一个hyper-v,而win10是hyper-v自动开启的一个虚拟机),所以win10对网卡的控制权可能有点问题,导致使用hyper-v作为底层的vagrant,无法对虚拟机进行静态IP的设置,每次开启关闭都会变动IP,这对我们的开发环境来说实在是太麻烦了。但是我又不想放弃docker的使用,于是我又查了一些资料,加深了对docker的理解。

解决方案

解决方案:其实docker是一个C/S结构的软件,我们日常使用的是docker的cli,而真正进行容器调度的,都是docker的守护进程。显然,2个进程是需要进行通信的,或者说,只要解决了通信的问题,我们就可以使用本地的docker-cli,去链接远程的docker守护进程。在折腾之前其实我也看到过这个知识,但是并没有放心里,所以折腾了一两天竟没有想到这里。

查阅了一些资料后,我测试了2种方案

  • 1种是使用docker-machine,这是docker自带的一种虚拟机方案,用docker-machine也可以创建虚拟机,然后将本地docker-cli连接到docker-machine启动的虚拟机中。但是它的功能主要是围绕docker的,所以虚拟机的管理功能比vagrant弱很多。
  • 第2种则是利用docker的remote API接口,使用vagrant,修改了VagrantFile,将开启的虚拟机里安装的docker的remote API接口打开,让它能够接收外部的请求,然后将本地docker的环境变量DOCKER_HOST指向虚拟机里的docker守护进程的端口,实现了从本地对虚拟机docker进行调用的功能。

毫无疑问,我最后选了第二种方案,因为论配置虚拟机本身的话,还是vagrant比较专业。最后的效果就是windows使用vagrant开启了一系列虚拟机,然后windows本地只安装了docker-cli,windows在命令行使用docker命令的时候,自动连接虚拟机docker环境进行调用。

远程控制

完成了windows对虚拟机的管理后,剩下的就是mac怎么连的问题了,这里又一次发挥了自己朴实的思维(汗- -),开了个teamviewer远程控制,然后远程连接windows,对家里的台式机进行操作。

emm。。。其实这样也不是不可以啦,但是着实有点笨拙了。因为其实我更需要的是windows开启的虚拟机,而不是windows本身。而且teamviewer搞不好哪天就检测说商业用途了,不够稳,而且远程控制毕竟还是体验不够好。于是接着折腾,就折腾到了下面的终极方案了。

终极方案:frp转发 + vscode remote develop

这个时候面临的问题就是:我怎么不用teamviewer之类的远程桌面工具,就连接到家里的机器了。又折腾了一两天,找到了神器frp。它的作用是,使用一个具有公网IP的机器,反向代理你内网的机器,进行端口映射,最后的效果就是,访问公网的IP和端口,自动转发到内网的IP和端口,从而实现了连接内网机器的目的。

于是我就开了一个google cloud的机器,开启了frps(frp的服务端),而在家里windows上开启了frpc(frp的客户端),使用google cloud对家里的机器进行端口转发,最后再在mac上连接到google cloud的一些转发的端口上,进而连接到了家里的windows和windows里虚拟机中。windows上使用winsw工具将frpc注册为了一个服务,开机自启动,并且买了一个开机棒。可以随时在远程将机器开机和关机。

于是我现在的开发模式就是:每天上班之后将家里电脑开机,然后使用mac上的vscode直接连接家里windows开的虚拟机进行开发工作,几乎感觉不到什么延迟,因为只是命令行的传输,数据量很小,而且google cloud的延迟只有20多ms。

遇到一些偶尔可能需要GUI操作的东西,就使用frp转发的微软远程桌面端口3389,远程桌面到windows进行一些简单的操作(此类操作其实很少,所以稍微有点延迟不怎么影响体验)。

使用了这套方案之后,就再也不担心开发环境的问题,和机器性能的问题了(反正顶配台式顶得住,hh),工作起来都感觉更有趣了~~😄

查看原文

赞 1 收藏 0 评论 0

mgic 赞了文章 · 2018-12-18

PHP 实现无限分类

最近打算做一个blog,通常每篇文章都有属于自己的分类。下面就记录下我在写blog时实现无限分类的过程。php框架用的是laravel,根据注释也能轻松改成你习惯的框架。

数据表设计

CREATE TABLE `article_category` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `pid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父id',
  `name` char(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '分类名',
  `statu` enum('y','n') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'y' COMMENT '是否显示',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `remark` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `article_category_pid_index` (`pid`)
) ENGINE=MyISAM AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

程序设计

添加分类

public function addClassify(Request $request)
{
    // laravel 框架自带的验证机制
    $this->validate(
        $request,
        [
            'name' => 'required|unique:article_category',
            'remark' => 'max:100',
            'pid' => 'required|numeric'
        ],
        [
            'name.required' => '请填写分类名!',
            'name.unique' => '改分类名已存在',
            'remark.max' => '分类简介不能超过100个字符',
            'pid.numeric' => '分类id必须为数字'
        ]
    );
    // 获取分类名
    $this->_category->name = $request->input('name');
    // 获取分类父id,默认是0,为一级分类
    $this->_category->pid = $request->input('pid',0);
    // 分类简介
    $this->_category->remark = $request->input('remark');
    // 写入数据库
    $result = $this->_category->save();
    // 返回结果
    $result = $result ? '操作成功' : '操作失败';
    return back()->with('act_msg',$result);
}

获取分类列表

/**
 * 加载视图
 * @return [type] [description]
 */
public function classify()
{    
    // 从数据库获取所有分类记录
    $node = $this->_category->orderBy('id','asc')->get();
    // 将分类以及子分类整理排序
    $node = $this->_treeNode($node->toArray(),0);
    // 加载视图及分配数据
    return view('admin.classify',['list'=>$node]);
}

/**
 * 整理排序所有分类
 * @param  array   $data       从数据库获取的分类
 * @param  integer $parentId 父id,默认一级分类
 * @return array 
 */
private function _treeNode($data,$parentId = 0)
{
    // 用于保存整理好的分类节点
    $node = [];
    // 循环所有分类
    foreach ($data as $key => $value) {
        // 如果当前分类的父id等于要寻找的父id则写入$node数组,并寻找当前分类id下的所有子分类
        if($parentId == $value ['pid']) {
            $node [$key] = $value;
            $node [$key] ['childer'] = $this->_treeNode($data,$value ['id']);
        }
    }
    return $node;
}    

方法classify是用于从数据库获取所有分类以及显示模板。方法_treeNode是一个递归函数。将从数据库获取的所有分类整理排序。排序好的效果如下图:

图片描述

渲染视图

<table class="table table-border table-bordered table-bg table-hover table-sort">
            <thead>
                <tr class="text-c">
                    <th width="25"><input type="checkbox" name="" value=""></th>
                    <th width="80">ID</th>
                    <!-- <th>标题</th> -->
                    <th width="120">分类名</th>
                    <th width="80">简介</th>
                    <!-- <th width="80">来源</th> -->
                    <th width="120">更新时间</th>
                    <th width="60">发布状态</th>
                    <th width="120">操作</th>
                </tr>
            </thead>
            <tbody>
            <!--遍历数据-->
            @foreach($list as $val)
                <tr class="text-c">
                    <td><input type="checkbox" value="" name=""></td>
                    <td>{{$val ['id']}}</td>
                    <td class="text-l">
                        <u title="查看">{{$val ['name']}}</u>
                    </td>
                    <td>{{$val ['remark']}}</td>
                    <td>{{$val ['updated_at']}}</td>
                    <td>
                        @if($val ['statu'] == 'y')
                            <span class="label label-success radius">启用</span> 
                        @else 
                            <span class="label label-danger radius">禁用</span> 
                        @endif
                    </td>
                    <td class="f-14 td-manage">
                        <a><i class="Hui-iconfont">&#xe6de;</i></a>
                         <a><i class="Hui-iconfont">&#xe6df;</i></a>
                          <a title="删除"><i class="Hui-iconfont">&#xe6e2;</i></a>
                    </td>
                </tr>
                <!--判断该分类下是否有子分类-->
                @if(!empty($val ['childer']))
                    {{get_childer_node($val ['childer'])}}
                @endif
            @endforeach
            </tbody>
        </table>

渲染视图时需要判断该分类下是否有子分类,如果只做到三级分类,此时只需要再来个二层循环就ok了。这边我自定义了一个递归函数get_childer_node 用于获取该分类下的子分类。具体实现如下:

/**
 * 获取子节点
 * @param  array  $data [description]
 * @return [type]       [description]
 */
function get_childer_node($data = [])
{
    // 记录该分类的深度
    static $callNum = 1;
    if(empty($data)) 
        return;
    foreach ($data as $key => $val) {
        if($val ['statu'] == 'y')
            $isShow = '<span class="label label-success radius">启用</span>';
        else
            $isShow = '<span class="label label-danger radius">禁用</span>';
        echo <<<HTML
                <tr class="text-c">
                <td><input type="checkbox" value="" name=""></td>
                <td>{$val ['id']}</td>
                <td class="text-l">|----{$val ['name']}</span></td>
                <td>{$val ['remark']}</td>
                <td>{$val ['updated_at']}</td>
                <td>$isShow</td>
                <td>
                    <a><i class="Hui-iconfont">&#xe6df;</i></a>
                    <a><i class="Hui-iconfont">&#xe6e2;</i></a>
                </td>
            </tr>
    HTML;
        // 如果该分类的依旧有子分类则再次遍历输出 
        if(!empty($val ['childer'])) {
            $callNum ++;
            get_childer_node($val ['childer']);
        }
        // 重置分类层级
        $callNum = 1;
    }
}

最终效果

图片描述

查看原文

赞 9 收藏 29 评论 5

mgic 关注了标签 · 2018-05-26

前端

Web前端开发是从网页制作演变而来的,名称上有很明显的时代特征。在互联网的演化进程中,网页制作是Web 1.0时代的产物,那时网站的主要内容都是静态的,用户使用网站的行为也以浏览为主。2005年以后,互联网进入Web 2.0时代,各种类似桌面软件的Web应用大量涌现,网站的前端由此发生了翻天覆地的变化。网页不再只是承载单一的文字和图片,各种富媒体让网页的内容更加生动,网页上软件化的交互形式为用户提供了更好的使用体验,这些都是基于前端技术实现的。

Web前端优化
  1. 尽量减少HTTP请求 (Make Fewer HTTP Requests)
  2. 减少 DNS 查找 (Reduce DNS Lookups)
  3. 避免重定向 (Avoid Redirects)
  4. 使得 Ajax 可缓存 (Make Ajax Cacheable)
  5. 延迟载入组件 (Post-load Components)
  6. 预载入组件 (Preload Components)
  7. 减少 DOM 元素数量 (Reduce the Number of DOM Elements)
  8. 切分组件到多个域 (Split Components Across Domains)
  9. 最小化 iframe 的数量 (Minimize the Number of iframes)
  10. 杜绝 http 404 错误 (No 404s)

关注 152426

mgic 关注了标签 · 2018-05-26

关注 81766

mgic 关注了标签 · 2018-05-26

关注 55419

mgic 关注了标签 · 2018-05-26

程序员

一种近几十年来出现的新物种,是工业革命的产物。英文(Programmer Monkey)是一种非常特殊的、可以从事程序开发、维护的动物。一般分为程序设计猿和程序编码猿,但两者的界限并不非常清楚,都可以进行开发、维护工作,特别是在中国,而且最重要的一点,二者都是一种非常悲剧的存在。

国外的程序员节

国外的程序员节,(英语:Programmer Day,俄语:День программи́ста)是一个俄罗斯官方节日,日期是每年的第 256(0x100) 天,也就是平年的 9 月 13 日和闰年的 9 月 12 日,选择 256 是因为它是 2 的 8 次方,比 365 少的 2 的最大幂。

1024程序员节,中国程序员节

1024是2的十次方,二进制计数的基本计量单位之一。程序员(英文Programmer)是从事程序开发、维护的专业人员。程序员就像是一个个1024,以最低调、踏实、核心的功能模块搭建起这个科技世界。1GB=1024M,而1GB与1级谐音,也有一级棒的意思。

从2012年,SegmentFault 创办开始我们就从网络上引导社区的开发者,发展成中国程序员的节日 :) 计划以后每年10月24日定义为程序员节。以一个节日的形式,向通过Coding 改变世界,也以实际行动在浮躁的世界里,固执地坚持自己对于知识、技术和创新追求的程序员们表示致敬。并于之后的最为临近的周末为程序员们举行了一个盛大的狂欢派对。

2015的10月24日,我们SegmentFault 也在5个城市同时举办黑客马拉松这个特殊的形式,聚集开发者开一个编程大爬梯。

特别推荐:

【SF 黑客马拉松】:http://segmentfault.com/hacka...
【1024程序员闯关秀】小游戏,欢迎来挑战 http://segmentfault.com/game/

  • SF 开发者交流群:206236214
  • 黑客马拉松交流群:280915731
  • 开源硬件交流群:372308136
  • Android 开发者交流群:207895295
  • iOS 开发者交流群:372279630
  • 前端开发者群:174851511

欢迎开发者加入~

交流群信息


程序员相关问题集锦:

  1. 《程序员如何选择自己的第二语言》
  2. 《如何成为一名专业的程序员?》
  3. 《如何用各种编程语言书写hello world》
  4. 《程序员们最常说的谎话是什么?》
  5. 《怎么加入一个开源项目?》
  6. 《是要精于单挑,还是要善于合作?》
  7. 《来秀一下你屎一般的代码...》
  8. 《如何区分 IT 青年的“普通/文艺/二逼”属性?》
  9. 程序员必读书籍有哪些?
  10. 你经常访问的技术社区或者技术博客(IT类)有哪些?
  11. 如何一行代码弄崩你的程序?我先来一发
  12. 编程基础指的是什么?
  13. 后端零起步:学哪一种比较好?
  14. 大家都用什么键盘写代码的?

爱因斯坦

程序猿崛起

关注 110373

认证与成就

  • 获得 0 次点赞
  • 获得 0 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 0 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2018-02-17
个人主页被 44 人浏览