Category: 编程、软件、技术

  • 数据库恢复

    【本文收录于[Go4Pro.org]

    4月24日早上手欠,不知道进行了什么骚操作,造成我的VPS上MySQL服务无法正常启动。

    以下是整个应急处理和数据库恢复过程。

    首先,我停掉了Apache2的服务,中断了WEB访问——因为反正也访问不了。

    然后,进入/var/lib/mysql目录,看到我之前的两个数据库的文件都还在,心里略微放心了一点。于是通过FileZilla将所有的idb和frm文件拷贝到本地。

    (more…)

  • Vagrant+VirtualBox最新SSH登录

    操作系统:Windows 10 64位 Vagrant:2.0.2 VirtualBox:5.2.8 虚拟机Linux:ubuntu/xenial64

    ======以上是分割线======

    不知道从什么时候开始,Vagrant+VB+Ubuntu的虚拟机组合就不能使用常规的用户+密码登录,而强行改用密钥登录。

    (more…)

  • Vagrant 1.9.3和Windows10

    【本文推送到[go4pro.org]

    最近升级到了Windows 10,Vagrant也升级到了1.9.3,Oracle VB也是最新的5.1.20。

    有几个小小的地方需要调整:

    (more…)

  • 用Tonido构建自己的私有云

    两个月前我略略总结了一下同步、版本和备份的概念,今天我又测试了一下用Tonido来构建自己的私有云。

    什么是云?

    什么是云?简单地说,云就是“生活在远方”的东西。我们平时在电脑上工作,用Word写文章、Excel做表格、PowerPoint做课件,保存的时候一般都会选择保存在自己本地的硬盘上。这样保存的文件被称为是“本地文件”,因为它存留在本地硬盘中。

    (more…)

  • 微信公众号、各类应用的隐私问题

    不知道最近大家是否在微信中收到过这么一条信息:

    IMG_0556

    我不知道发出这条消息的那位微信好友是出于什么目的:是真心地认为自己微信好友太多,也真心地认为不知出于什么原因被僵尸粉看上了,或者被别人屏蔽了,所以要从中知道自己真正的粉有多少;还是出于什么商业推广目的,因为在这条消息中明确出现了一个所谓平台的微信号;还是因为被感染了什么微信病毒,在自己不知情的情况下发送了这么一条信息;还是脑子进了水,根本没有对自己微信好友的隐私的保护?

    (more…)

  • 同步、版本和备份

    在日常工作中,我们要和各种文件打交道。而创建、修改是最常见的操作。

    也同样是在日常工作中,我们也会有在多台电脑上工作的经历。比如说,在公司的电脑上创建了一个Excel文件,进行了一些输入但没有完成,想回家继续完成。但是又不想把公司的电脑带回家(或者是台式机而带不回家),这时该怎么办呢?

    一种方法是用U盘把文件拷贝带回家,或者用邮件把这个文件发回自己的邮箱回家收取后继续工作。当然也可以考虑将文件存放到网盘之类的方法。(当然,前提是这样做是公司IT政策允许的。如果公司IT政策不允许,那么看到此处就可以打住了。)

    这些方法都有一个缺点:都要手动地将文件“搬来搬去”,而一旦文件修改次数增加,来回拷贝时只能靠文件的更新时间作为“哪个是最新版本”的判断依据。但是这个判断有时是会有问题的。比方说,在公司进行修改后忘记更新到U盘或者网盘,而回家后在老的版本上继续工作等等。

    为了避免这个问题,我采用的是“同步”的方法,采用的软件是Resilio Sync。Resilio的前身是BitTorrent Sync,出品方是赫赫有名的BitTorrent协议的开发商。

    这是一个P2P的软件,不需要设置服务器,也不借助于任何公共服务,完全是一个私有云的架构。

    软件安装和设置都很简单,而且支持目前所有的主流操作平台:Windows,Linux,Mac,Android,iOS。在iOS和Android上,它还可以同步照片。这样一来,你再也不用担心照片丢失的问题。

    Resilio Sync还有一个“黑”应用场景,那就是可以同步电影。


    一个文件光有同步还是不够的。有时我们会修改文件,再修改,再修改……有一种做法当然很实际,就是不同的修改生成不同的文件(V1,V2……)。不过一般会推荐用标准的版本控制软件(Git,hg)去完成。

    使用版本控制最好是去国际上主流的版本控制站点注册一个账号,比如github或者BitBucket。虽然github名气更大,但是我更推荐BitBucket,因为它可以在免费账号的情况下生成私有仓库。

    Windows下git的客户端很多,我向大家推荐的是GitKraken或者SourceTree,而且这两个软件都是多平台支持,GitKraken更是全平台支持。

    有了版本,我们随时可以切换到不同的版本进行工作。

    在某些情况下,版本控制可以当做备份来用。


    最后我们谈一谈备份。我强调一点:一定要经常做备份。一些文件(特别是老照片)丢失的后果是无法弥补的。

    备份必须是在另外一个硬盘上进行,更好的是在另外一台机器上完成,如果有条件进行异地备份就完美了——不过这点要求太高了。

    我目前用的是SuperEasyBackup Pro,付费了。它的备份速度很快,特别是在后期增量备份的情形下。我的备份位置是一个独立的1T外挂硬盘,它一直挂在我需要备份的电脑的USB口上。


    新年就要来到,祝大家新年快乐,阖府安康!

  • 任氏有无轩维客上线

    我有两个主力站点。一个是“任氏有无轩”(藏书、读书、博客),这个也是我日常更新最多的站点。另一个是“任氏有无轩维客”(项目、资源),这个会在我完成了一些比较大的项目,而且这些项目不适宜放在“任氏有无轩”中时上传到维客站点中。

    维客站点其实已经开了一段时间,期间项目也在不断累积。这几天我用Spress这个软件对我的维客进行了完全的静态化。 所谓的静态化就是站点中所有的文件都是静态的HTML文件。这样做的好处是很明显的:

    • 完全的Markdown语法控制;
    • 完全的Twig引擎定制;
    • 更快的加载速度;
    • (也许)更好的SEO;

    目前在这个维客中有四个比较大的项目:《911调查委员会报告》《这本书叫什么?》《上帝创造了整数》《卫斯理全集》。 欢迎大家关注!

    附:桌面和手机浏览效果

    Ashampoo_Snap_2016.12.18_10h05m59s_003_ChromeScreenshot_20161218-101321

  • 一个很NB的插件:Zemanta

    最近在翻译一本书,讲的是搜索的未来发展。其中提到了这么一个插件:Zemanta

    这个插件的功能是:你在写作的时候,插件会在后台检测你的书写内容,并根据上下文建议相关的博客文章和图片。这是很了不起的一个工作啊!

    (more…)

  • Microsoft Power BI初尝试

    最近测试了一下Microsoft Power BI Desktop。用的是我的藏书数据库。

    注意事项一:BID访问MySQL数据库需要安装MySQL .NET Connector,官方下载地址:http://dev.mysql.com/downloads/connector/net/

    注意事项二:BID不能单独Export图片,而只能用服务器端控件的方式显示。如下图。所以你还需要去官网下载Desktop并注册一个账号(特别注意:注册中的国家列表没有“中国”,但是你选择随便一个地方也无所谓;另外,不能用任何类型的免费邮箱)。

    还有很多要学习的地方。慢慢来。

    5.14补充:

    • 发现一个问题:我修改了图表,也已经publish,但是在本页面上还是显示老的图表。重新贴上BI里给出的链接还是老的图表。解决方法是克隆这个修改后的表格,再导出Web链接即可。
  • 微信订阅号的开发

    最近看了一下微信订阅号的开发。

    我要做一个个人订阅号,用户订阅之后,可以通过输入命令获得交互,得到英文单词的解释,大概就是这样。

    微信开发权限获得就不讲了,需要帮助的同学可以去访问相应的站点。

    首先,我开了一个域名(http://weixin.rsywx.com) 作为和微信通讯的接口。

    按照微信的说法,用户输入命令后,该接口将“被动”地回复信息。而这也是我这个订阅号和用户交互的主要渠道。

    在weixin.rsywx.com中,我用Silex框架构建了我的应用。这是因为我需要在这个框架中进行一些控制。当然你也可以用一个plain PHP文件来完成这个接口的工作。 该应用的入口文件很简单:

    require_once __DIR__ . '/../vendor/autoload.php';
    require_once __DIR__ . '/./WechatCallbackAPI.php';
    $app = new Silex\Application();
    $app['debug'] = true;
    // Twig registration
    $app->register(new Silex\Provider\TwigServiceProvider(), ['twig.path' => __DIR__ . '/../views']);
    $app->post('/', function () use ($app)
    {
        $obj=new WechatCallbackAPI();
        echo $res=$obj->response($app);
    });
    $app->run();

    其中的Twig注册不是必要的,因为微信要求的回应是一个XML字符串。不过放进去也没有关系。 对于“/”这个路径,我们在响应微信的请求时必须使用POST方式。同时我们创建了一个对象,并调用response方法来返回消息。 在WechatCallbackAPI中,我们抄袭微信的实例代码并作一些改进:

    public function response($app)
        {
            $post=$GLOBALS['HTTP_RAW_POST_DATA'];
            //$post=file_get_contents('php://input');
            if(!empty($post))
            {
                libxml_disable_entity_loader(true);
                $obj=simplexml_load_string($post, 'SimpleXMLElement', LIBXML_NOCDATA);
                $from=$obj->FromUserName;
                $to=$obj->ToUserName;
                $key=strtolower(trim($obj->Content));
                if($key==?||$key==?||$key=='help')
                {
                    $wpme=new WPME($from, $to);
                    $res=$wpme->help();
            return $res;
                }
                else if (substr($key, 0,4)=='wpme')
                {
                    $wpme=new WPME($from, $to);
                    $wpme->setKey($key);
                    $res=$wpme->invoke();
                    return $res;
                }
                else if(substr($key, 0,4)=='wotd')
                {
                }
                else
                {
                    $wpme=new WPME($from, $to);
                    $res=$wpme->unknown();
                    return $res;
                }
            }

    注意,这里还用到了一个在PHP 5.6中被标记为deprecated,而在PHP 7将是obsolete的功能:

    $post=$GLOBALS['HTTP_RAW_POST_DATA'];

    PHP手册中建议用

    <pre lang="php">$post=file_get_contents('php://input');

    但是经过测试似乎不行。微信就是这么任性。

    在该response函数中,我们根据不同的用户输入来调用不同的功能。上述代码中列出了WPME(Word Power Made Easy)模块中的判断。WPME模块中最重要的方法是invoke,它将根据不同的命令($key)去进一步调用不同的资源并构造返回值。而另外一些命令在WPME中直接处理,比如最简单的help方法:

    public function help()
        {
            $content = Available commands:\nwpme1: Latest WPME\nwpme7: Last 7 WPMEs\nwpme????: Search WPME for ????;
            $res = sprintf(WPME::$txtTemplate, $this->from, $this->to, time(), $content);
            return $res;
        }

    help将列出可以使用的命令,比如wpme1,然后渲染一个静态文本模板并返回。文本模块的格式可以参考微信文档。

    而invoke方法如下:

    public function invoke()
        {
            $uri = https://rsywx.net/wechat/ . htmlentities($this->key);
            $content = file_get_contents($uri);
            preg_match_all('/(.*?)<\/title>/i', $content, $matches);
            $res = sprintf(WPME::$newsTemplate, $this->from, $this->to, time(), $matches[1][0], date('Y-m-d'), $uri);
            return $res;
        }

    我们可以看到,我们的一般命令将返回图文信息。而图文信息的模板格式也请参考微信文档。这里我们并不进行任何实质性的处理,真正的内容渲染我们在另外一个站点:https://rsywx.net 中进行。

    rsywx.net是一个之前我单独开发的站点,考虑到微信使用的一些功能可以在该站点中复用,所以我将微信需要的返回信息的功能(控制、数据、呈现)放在这里实现。这个站点用Symfony完成。其实,我这个微信号最本质的内容呈现逻辑都是在rsywx.net中完成的。

    我们看一个indexAction方法。这个方法接受来自weixin.rsywx.com的调用,并根据不同的关键字进行处理:

    public function indexAction($key)
        {
            $entity = substr($key, 0, 4);
            if ($entity == 'wpme')
            {
                if ($key == 'wpme1' || $key == 'wpme7')
                {
                    $uri = http://api/$entity/$key;
                    $res = json_decode(file_get_contents($uri))->out;
                    $theme = $this->container->getParameter('theme');
                    return $this->render(AppBundle:$theme/wechat:$key.html.twig, ['res' => $res->res]);
                }
                else //The key is like wpme????, where ???? is the search term
                {
                    $search = substr($key, 4);
                    $uri = http://api/$entity/s/$search;
                    $res = json_decode(file_get_contents($uri))->out;
                    $theme = $this->container->getParameter('theme');
                    return $this->render(AppBundle:$theme/wechat:wpme7.html.twig, ['res' => $res->res]);
                }
            }
        }

    如果从weixin传来的命令是wpme1(列出最新的单词)或者wpme7(列出7个最新的单词),那么rsywx.net将进一步调用http://api.rsywx.com 中相应的RESTful API接口获得数据并渲染;如果是类似wpme????这样的命令,那么将进行搜索,并将结果返回。

    最后我们来看http://api.rsywx.com ,如果我们直接访问这个站点,将会呈现该站点所提供的所有接口的API文档:

    Ashampoo_Snap_2016.02.01_20h46m03s_002_Chrome

    而在这个站点中,我同样用Silex框架实现了对应的方法来返回数据(实际上,rsywx.net的所有数据也都是由该站点提供的)。

    好了,如果你现在在公众号中输入这样的一个命令:wpme1,你将看到如下的界面:

    Screenshot_20160201-205011

    Screenshot_20160201-205018

    怎么样?是不是很酷?

    本文收录于[go4pro.org]