解决Ubuntu下Sublime不能输入中文

  • 首先下载sublime-text-imfix,这是一个用ShellC编写的插件。
    $ git clone https://github.com/lyfeyaj/sublime-text-imfix.git
    
  • subl移动到/usr/bin,并且将sublime-imfix.so移动到/opt/sublime_text/(sublime的安装目录)
    $ cd ~/sublime-text-imfix
    $ sudo cp ./lib/libsublime-imfix.so /opt/sublime_text/
    $ sudo cp ./src/subl /usr/bin/
    

    以上~只是为根目录,因为再第一步中打开终端后,默认位置在~,你可以选择下载到其他目录,自然相应的也要更改后面的~

  • subl命令尝试能不能启动sublime,如果成功启动的话,应该是可以输入中文的。
    $ subl
    
  • 终端输入:
    $ LD_PRELOAD=./libsublime-imfix.so subl
    
  • 但是这样只能用上述命令才能输入中文,也就是启动能输入中文的版本。所以为了方便,我们再新建一个shell脚本。
     $ cd home 
    $ vim sublime
    

    于是我们在home目录下新建了一个sublime文件,接着输入:

    #!/bin/bash
    LD_PRELOAD=/opt/sublime_text/libsublime-imfix.so subl
    

    接着esc退出编辑模式,:wq保存退出。

  • 至此,我们就完成了所有工作。想要启动,直接终端输入bash ~/sublime,就可以启动sublime,并且可以输入中文。
  • 如果不需要输入中文,直接按照以前的方式打开即可。建立脚本的目的是为了能方便地打开能输入中文的sublime。

深入理解Javascript定时器是如何工作的

[译]JavaScript中的定时器是如何工作的?

如有问题,欢迎指正

原文链接:http://ejohn.org/blog/how-javascript-timers-work/

在一个基础阶段,理解JavaScript定时器的工作原理的是非常重要的。通常它们看起来不那么直观,因为它们处于单线程中。让我们从我们将接触的这三个函数开始,它们是用来构造和操作计时器的。

  • var id = setTimeout(fn, delay) – 启动一个定时器,它将调用参数中的函数在延迟时间之后。这个函数将将返回一个独一无二的ID用来被指定以取消这个定时器。
  • var id = setInterval(fn, delay) – 和setTimeout()相似,但将持续地调用参数中的函数每间隔一个延迟时间,除非它被取消。
  • clearInterval(id)clearTimeout(id) – 传入一个定时器ID(即上述函数传回的ID)并停止定时器回调。

为了理解定时器内部是如何工作的,还有一个重要的概念需要理解就是:定时器的延迟时间是无法保证的。由于浏览器中的所有JavaScript都在单个线程上执行,因此异步事件(例如鼠标点击和计时器)只会在执行中出现打开时运行。这最好以图表来解释,如下图:

Timers

这张图中包含了大量的信息要研究,但理解它会让你对异步JavaScript执行是如何工作有一个更深刻的认识。这张图是一维的,在垂直方向我们能看到图中标着事件,以毫秒为单位。蓝色的盒子代表着JavaScript正在被执行的部分。例如第一块JavaScript大概执行18毫秒,鼠标点击那块大约11毫秒等等。

因为JavaScript一次只能执行一段代码(由于它的单线程特性),所以每个代码块都“阻塞”了其他异步事件的进度。这意味着当一个异步事件发生时(如鼠标点击,计时器触发或是XMLHttpRequest完成),它会排队等待稍后执行。(实际中排队是如何进行的,不同的浏览器情况不同,因此这里我们考虑的时候将它理想化)。

首先,在第一个JavaScript块中,启动了两个计时器,分别是10毫秒的setTimeout()和10毫秒的setInterval()。虽然我们可以清楚地看到它是何时何地计时器被触发,但实际上这发生在第一个代码块完成之前。但是,请注意,它并没有马上被执行(它不能这样做,因为线程的原因)。相反地,延迟功能被排队,以便在下一个可以被执行的时刻执行。

此外,在第一个JavaScript块中,我们看到发生了一个鼠标点击事件。于是与这个异步事件关联的JavaScript回调(由于我们不知道用户何时会执行一个动作,因此我们认为它是异步的)不能立即执行。因此和初始的定时器类似,它被排队等待执行。

在JavaScript完成执行浏览器的初始块之后立即提出了问题:接下来是什么等待被执行?此时鼠标点击程序和计时器回调都在等待。于是浏览器选择了一个(鼠标点击回调)并立刻执行了它。于是计时器将等到下一次可能执行的时间以便执行。

注意当鼠标点击程序在执行时,第一个间隔回调也执行了。与定时器一样,其处理程序也排队等待执行。但是注意,当间隔再次被触发时(同时计时器程序正在执行),这次将删除处理程序。如果在一大块代码正在被执行的时候将所有的间隔回调排队等待执行,那么当这一大块代码完成后将是一大堆间隔执行程序,并且它们之间没有延迟。相反,在给更多的间隔处理程序排队前,浏览器往往只是等待直到没有更多的间隔处理程序在排队。

事实上,我们可以看到,这是第三个间隔回调触同时间隔处理程序本身正在被执行的情况。从中我们可以发现一个事实,就是:间隔程序并不在意正在执行的是什么,它们会不加区别地排队,即使这意味着回调之间的时间会被牺牲。

最终,在第二个间隔回调被执行后,我们可以看到这里没有东西等待JavaScript引擎去执行。这意味着浏览器现在等待新的异步事件发生。这发生在50毫秒标记处,也就是间隔再次被触发。但这一次没有东西阻塞它的执行,所以它立刻被触发了。

让我们从下面的例子中更好的理解setTimeout()setInterval()之间的区别。

/* Some long block of code… */
setTimeout(arguments.callee, 10);
 }, 10);

setInterval(function(){
/* Some long block of code… */
 }, 10);

这两段代码乍一看在功能上看起来似乎是一样的,但实际上不是的。值得注意的是,在前一个回调执行之后,setTimeout()至少会有10毫秒的延迟。(它可能会更多,但至少不会少),而setTnterval()会尝试每10毫秒执行一次回调,而不考虑何时执行最后一次回调。

到目前为止我们学了很多,让我们总结一下:

  • JavaScript引擎只有一个线程,也就是单线程,迫使异步事件排队等待执行。
  • setTimeout()setInterval()在如何执行异步代码上有根本的不同。
  • 如果一个计时器被阻塞无法立即执行,它将被推迟到下一个可能执行的时刻(这将导致它比期望的延迟时间更长)。
  • 如果它将花费足够长的时间(超出了指定的推迟时间),间隔将会一个接着一个地无间隔执行。

所有的这些都是非常重要的知识,了解JavaScript引擎工作的原理,尤其是大量的异步事件发生的情况,为构建一个高级应用程序打下良好的基础。

深入理解JavaScript运行机制

深入理解JavaScript运行机制

前言

  • 本文是写作在给团队新人培训之际,所以其实本文的受众是对JavaScript的运行机制不了解或了解起来有困难的小伙伴。也就是说,其实真正的原理和本文阐述的并不完全符合,就如中学课本和大学课本一样,大学老师会告诉你高中的一些东西是在某些理想情况下得到的结论,本文同理。
  • 本文的目的是希望大家阅读之后能对JavaScript的运行机制有一个比较直观比较快的认识,但更重要的是自己动手实践,只有实践才能真正发现问题和得到提升:)
  • 收到了大家的支持和反馈,非常感谢:)

想要理解JavaScript的运行机制,需要分别深刻理解以下几个点:

  • JavaScript的单线程机制
  • 任务队列(同步任务和异步任务)
  • 事件和回调函数
  • 定时器
  • Event Loop(事件循环)

JavaScript的单线程机制

JavaScript的一个语言特性(也是这门语言的核心)就是单线程。什么是单线程呢?简单地说就是同一时间只能做一件事,当有多个任务时,只能按照一个顺序一个完成了再执行下一个。

JavaScript的单线程与它的语言用途是有关的。作为一门浏览器脚本语言,JavaScript的主要用途是完成用户交互、操作DOM。这就决定了它只能是单线程,否则会导致复杂的同步问题。

设想JavaScript同时有两个线程,一个线程需要在某个DOM节点上添加内容,而另一个线程的操作是删除了这个节点,那么浏览器应该以谁为准呢?

所以为了避免复杂性,JavaScript从诞生起就是单线程。

为了提高CPU的利用率,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以这个标准并没有改变JavaScript单线程的本质。

任务队列

一个接一个地完成任务也就意味着待完成的任务是需要排队的,那么为什么会需要排队呢?

通常排队有以下两种原因:

  • 任务计算量过大,CPU处于忙碌状态;
  • 任务所需的东西为准备好所以无法继续执行,导致CPU闲置,等待输入输出设备(I/O设备)。> 比如有的任务你需要Ajax获取到数据才能往下执行

由此JavaScript的设计者也意识到,这时完全可以先运行后面已经就绪的任务来提高运行效率,也就是把等待中的任务先挂起放到一边,等得到需要的东西再执行。就好比接电话时对方离开了一下,这时正好有另一个来电,于是你便把当前通话挂起,等那个通话结束后,再连回之前的通话。

所以也就出现了同步和异步的概念,任务也被分成了两种,一种是同步任务(Synchronous),另一种是异步任务(Asynchronous)。

  • 同步任务:需要执行的任务在主线程上排队,一个接一个,前一个完成了再执行下一个
  • 异步任务:没有马上被执行但需要执行的任务,存放在“任务队列”(task queue)中,“任务队列”会通知主线程什么时候哪个异步任务可以执行,然后这个任务就会进入主线程并被执行。> 所有的同步执行都可以看作是没有异步任务的异步执行

具体来说,异步执行如下:

  • 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。

    也就是所有能被马上执行的任务都在主线程上排好了队,一个接一个的被执行。

  • 主线程之外,还存在一个“任务队列”(task queue)。只要异步任务有了运行结果,就在“任务队列”之中放置一个事件。

    也就是说每个异步任务准备好了就会立一个唯一的flag,这个flag用来标识对应的异步任务。

  • 一旦“执行栈”中的所有同步任务执行完毕,系统就会读取“任务队列”,看看里面有哪些事件。那些对应的异步任务,就结束等待装袋,进入执行栈开始被执行。

    也就是主线程把之前的任务做完了之后,就会来看“任务队列”中的flag,来把对应的异步任务打包来执行。

  • 主线程不断重复以上三步。

    只要主线程空了,就会去读取“任务队列”。这个过程会被不断重复,这就是JavaScript的运行机制。

事件和回调函数

事件

“任务队列”是一个事件的队列(也可以理解成是消息的队列),IO设备完成一项任务,就会在“任务队列”中添加一个时间,表示相关的异步任务可以进入“执行栈”。接着主线程读取“任务队列”,查看里面有哪些事件。

“任务队列”中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入“任务队列”,等待主线程读取。

回调函数

所谓“回调函数”(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。

“任务队列”是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,“任务队列”上第一位的事件就自动进入主线程。但是,如果包含“定时器”,主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。

Event Loop

主线程从“任务队列”中读取事件,这个过程是循环不断的,所以整个的运行机制又称为“Event Loop”(事件循环)

为了更好地理解Event Loop,下面参照Philip Roberts的演讲中的一张图。

Event Loop

上图中,主线程在运行时,产生了heap(堆)和stack(栈),栈中的代码调用各种外部API,并在“任务队列”中加入各种事件(click,load,done)。当栈中的代码执行完毕,主线程就会读取“任务队列”,并依次执行那些事件所对应的回调函数。

执行栈中的代码(同步任务),总是在读取“任务队列”(异步任务)之前执行。

var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function (){};
req.onerror = function (){};
req.send();

上面的代码中的req.send方法是Ajax操作向服务器发送数据,它是一个异步任务,意味着只有当前脚本的所有代码执行完,系统才会去读取“任务队列”。所以,它与以下的写法是等价的。

var req = new XMLHttpRequest();
req.open('GET', url);
req.send();
req.onload = function (){};
req.onerror = function (){};

也就是说,指定回调函数的部分(onload和onerror),在send()方法的前面或后面是无关紧要的,因为它们属于执行栈的一部分,系统总是执行完它们才会去读取“任务队列”。

定时器

除了放置异步任务的事件,“任务队列”还可以放置定时事件,即指定某些代码在多少时间之后执行。这叫做定时器(timer)功能,也就是定时执行的代码。

SetTimeout()setInterval()可以用来注册在指定时间之后单次或重复调用的函数,它们的内部运行机制完全一样,区别在于前者指定的代码是一次性执行,后者会在指定毫秒数的间隔里重复调用:

setInterval(updateClock, 60000); //60秒调用一次updateClock()

因为它们都是客户端JavaScript中重要的全局函数,所以定义为Window对象的方法。

但作为通用函数,其实不会对窗口做什么事情。

Window对象的setTImeout()方法用来实现一个函数在指定的毫秒数之后运行。所以它接受两个参数,第一个是回调函数,第二个是推迟执行的毫秒数。 setTimeout()setInterval()返回一个值,这个值可以传递给clearTimeout()用于取消这个函数的执行。

console.log(1);
setTimeout(function(){console.log(2);}, 1000);
console.log(3);

上面代码的执行结果是1,3,2,因为setTimeout()将第二行推迟到1000毫秒之后执行。

如果将setTimeout()的第二个参数设为0,就表示当前代码执行完(执行栈清空)以后,立即执行(0毫秒间隔)指定的回调函数。

setTimeout(function(){console.log(1);}, 0);
console.log(2)

上面代码的执行结果总是2,1,因为只有在执行完第二行以后,系统才会执行“任务队列”中的回调函数。

总之,setTimeout(fn,o)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是尽可能早地执行。它在“任务队列”的尾部添加一个事件,因此要等到同步任务和“任务队列”现有的事件都处理完,才会的到执行。

HTML5标准规定了setTimeout()的第二个参数的最小值(最短间隔),不得低于4毫秒,如果低于这个值,就会自动增加。

需要注意的是,setTimeout()只是将事件插入了“任务队列”,必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数。要是当前代码耗时很长,有可能要等很久,所以并没有办法保证回调函数一定会在setTimeout()指定的时间执行。

由于历史原因,setTimeout()setInterval()的第一个参数可以作为字符串传入。如果这么做,那这个字符串会在指定的超时时间或间隔之后进行求值(相当于执行eval())。

关于深入理解定时器的工作原理,这里推荐阅读jQuery的作者John Resig的一篇文章: http://ejohn.org/blog/how-javascript-timers-work/

我自己也翻译了这篇文章,如有问题,欢迎指正:http://guoxunique.com/2016/12/07/how-javascript-timers-work/

参考阮一峰老师的博文 http://www.ruanyifeng.com/blog/2014/10/event-loop.html

参考《JavaScript权威指南》

What you don’t know about console

本文参考:

https://segmentfault.com/a/1190000006721606
http://www.html5cn.org/article-9690-1.html

通常用法

大家都会有用log,但很少有人能够很好地利用console.error或console.warn等将输出到控制台的信息进行分类整理。他们功能区别不大,意义在于将输出到控制台的信息进行归类,或者说让它们更加语义化。

  • 打印字符串:console.log("普通信息");
  • 打印提示消息:console.info("提示性信息");
  • 打印警告消息:console.warn("警示信息");
  • 打印错误消息:console.error("错误信息");
  • 打印调试信息:console.debug("debug");

高级用法

查看所有方法

console除了上面的几个最常见的方法之外还有什么方法呢?log除了能打印字符串外,还能打印对象,我们可以利用console.log打印自己。

在Console输入:

console.log(console);

输出:

Console.log(console)

于是我们可以看到有这么多的console方法,但这不等于每个浏览器都能实现。所以说,这个特性是非标准的,请尽量不要在生产环境中使用它。

但是我们可以在开发环境中,合理的利用这些方法来帮助我们开发。

清理控制台

当我们在控制台调试时,有时候会需要清理控制台中的内容。浏览器和命令行clear一样,提供了一个清理函数console.claer()

console.clear()

当然我们也可以用chromecommand line api来清理控制台。

clear()

又或者可以使用按键:Mac上的cmd+k,Win上的ctrl+l(我使用的是chrome浏览器)。

分组

当代码非常长,或者我们需要把一个函数,或者一个文件中的函数等区分出来。我们可以使用分组来实现,这也是将分类管理的思想发挥到极致。这适合在开发一个规模很大模块很多很复杂的Web APP时,将各自的log信息分组到以各自命名空间为名称的组里面。

在Console输入:

console.group("group1");
console.log("aaa");
console.log("bbb");
console.groupEnd();

console .group("group2");
console.log("ccc");
console.log("ddd");
console.groupEnd();

输出:

console.group()

如果希望输出信息为折叠的,可以使用console.groupCollapsed,用法同console.group

查看对象信息

有时候我们需要打印出对象信心,可以使用console.log来进行简单的输出。

在Console输入:

var Obj = {
    proprety1: value1,
    property2: value2,
    property3: value3
};
console.log(Obj);

于是你会发现这个输出信息并不利于我们观察,于是我们可以使用console.table来帮助我们清楚的显示关联数组信息

var data = [
    {
        "proprety1": "value1",
        "property2": "value2"
    },
    {
        "proprety1": "value3",
        "property2": "value4"
    }
];
console.table(data);

输出:

console.table()

以及有的时候后端传回来一大串数据,直接console.log或是通过抓包工具查看或许都会让人晕头转向,这个时候也是console.table发挥作用的时候,以表格的形式呈现数据,一目了然。

但是如果想要看到详细的对象信息,我们可以使用console.dir,将一个JavaScript对象的所有属性和属性值显示成一个可交互的列表,它还能打印出函数等。

console.dir(clear);

console.dir将DOM节点以JavaScript对象的形式输出到控制台,而console.log是直接将该DOM节点以DOM树的结构进行输出,与在元素审查时看到的结构是一致的。

console.dir(document.body);
console.log(document.body);

如果你想要查看某个节点中的HTML代码,可以用console.dirxml来查看页面中对应元素的html/xml内容。

HTML代码:

<div id="flag">

message

</div>

JavaScript代码:

var flag = document.getElementById("flag");
console.dirxml(flag);

性能测试

有时候当我们完成了一段代码我们想要知道这段代码的性能如何。这是我们可以使用console.timeconsole.timeEnd,他们可以记录代码运行所花费的时间。

console.time("test");
(function () {
    for(var i = 0; i < 10; i++) {
        var sum = (function () {
            var flog = 0;
            for(var i = 0; i < 10; i++) {
                flog+=i;
            }
        })();
    }
})();
console.timeEnd("test");

所以这个性能测试的本质就是个计时器,无独有偶,还有一对叫做console.profileconsole.profileEnd

console.profile("test");
(function () {
    for(var i = 0; i < 10; i++) {
        var sum = (function () {
            var flog = 0;
            for(var i = 0; i < 10; i++) {
                flog+=i;
            }
        })();
    }
})();
console.profileEnd("test");

其输出结果会显示在profile中。

当想要查看CPU使用相关信息时,可以使用console.profile配合console.profileEnd来完成这个需求。
这一功能可以通过UI界面来完成,Chrome开发者工具里面有个tab便是Profile。使用方法和console.time基本一样,其实time开发者工具里也有个tab就是timeline。

此外,如果还想要知道运行时的结果栈,可以使用console.trace

在Console输入:

function add(num) {
    if (0 < num) {
        console.trace("现在num的值为", num);
        return num + add(num - 1);
    } else {
        return 0;
    }
}

var a =3;
add(3);

输出:

判断真假

平时我们在写代码时经常需要判断一下当前值的真假情况,使用if或者三元表达式来达到目的。我们现在也可以使用console.assert来判断,它会先对传入的表达式进行断言,只有表达式为false时,才会返回一个console.error的结果到控制台。

console.assert(1 == 1);
console.assert(1 == 0);
console.assert(!(1 == 0));

统计次数

有时候我们需要统计一个函数被调用了几次,我们通常会增加一个变量count来记录,然后在控制台中查看。这样相当的麻烦,我们可以使用console.count函数来帮忙我们记录次数,并输出。

function hi(name) {
console.count(name);
return "hi " + name;
}   

for(var i = 0; i < 10; i++) {
    if(i < 4) {
        hi("person");
    } else {
        hi("god");
    }
}

$

我们知道PHP中满屏都是$。而在Chrome里,$用处同样是多且方便。

2+2//回车,再
$_+1//回车得5

上面的$_需要领悟其奥义才能使用得当,而$0~$4则代表了最近5个你选择过的DOM节点。
这是什么意思呢?在页面右击检查(审查元素),然后在弹出的DOM节点树上点选,这些被点选的节点会被记录下来,而$0则会返回最近一次点选的DOM节点,以此类推,$1返回的是上上次点选的DOM节点,最多保存了5个,如果不够5个,则会返回undefined。

另外值得称赞的是,Chrome控制台中原生支持类jQuery的选择器,也就是说你可以用$加上熟悉的CSS选择器来选择DOM节点。

$("body");
$("div");

而$(selector)返回的实际上是满足选择条件的首个DOM元素。
深入一步,其实$(selector)是原生JavaScript document.querySeletor()的封装。
同时另一个命令$$(selector)返回的是所有满足选择条件的元素的一个集合,是对document.querySelectorAll()的封装。

$x(path)

将所匹配的节点放在一个数组里返回

$x("//p");
$x("//p[a]");

$x(path)匹配节点
$x("//p")匹配所有的p节点,$x("//p[a]");匹配所有子节点包含a的p节点

copy

copy(document.body)

然后你就可以Ctrl+V了。
注意:它不依附于任何全局变量比如Window,所以其实在JS代码里是访问不了这个copy方法的,所以从代码层面来调用复制功能也就无从谈起。

Keys & values

关于键值对,前者返回传入对象所有属性名组成的数组,后者返回所有属性值组成的数组。例如:

var tfboy={name:'wayou',gender:'unknown',hobby:'opposite to the gender'};
keys(tfboy);
values(thboy);

Keys&values

monitor & unmonitor

monitor(function),它接收一个函数名作为参数,比如function a,每次a被执行了,都会在控制台输出一条信息,里面包含了函数的名称a以及执行时传入的参数。而unmonitor(function)便是用来停止这一监听。

function sayHello(name){
    alert('hello,'+name);
}
monitor(sayHello);
sayHello('damonare');
sayHello(‘tjz');
unmonitor(sayHello);

monitor&unmonitor

debug & undebug

debug同样也是接收一个函数名作为参数。当该函数执行时自动断下来以供调试,类似于在该函数的入口处打了个断点,可以通过debugger来做到,同时也可以通过在Chrome开发者工具里找到相应源码然后手动打断点。而undebug则是接触该断点。

一个酷炫的黑魔法

console.log家族还提供了一个API:第一个参数可以带一些格式化命令,比如%c,\n;

console.log('%chello world', 'background-image:-webkit-gradient( linear, left top, right top, color-stop(0, #f22), color-stop(0.15, #f2f), color-stop(0.3, #22f), color-stop(0.45, #2ff), color-stop(0.6, #2f2),color-stop(0.75, #2f2), color-stop(0.9, #ff2), color-stop(1, #f22) );color:transparent;-webkit-background-clip: text;font-size:5em;');

console.log第一个参数带格式化命令

当然图片也是可以的,大家可以自行尝试,修改上述代码即可。

另外,console.log()接收不定参数,参数间用逗号分隔,最终输出会将它们以空白字符连接。

console.log接收不定参数

总结

console中有很多对我们调试代码有帮助的函数,在开发环境中使用console来调试代码,可以让我们的测试更加便利。

How to restore Ubuntu grub

How to restore Ubuntu grub

As we know, windows will destory the GRUB if you install it with Ubuntu installed first.So how to fix GRUB?

I found a great solution on a blog. The steps are as follows:

  1. boot with a Ubuntu LiveCD(U disk), and choose try Ubuntu without install
  2. type $ sudo fdisk -l in terminal to find out where you installed Ubuntu.

I installde in sda1(maybe not same as you)

  1. type $ sudo -i to get the the ability to run commands as root.
  2. type $ mkdir /media/tmpdir to create a temporary folder.
  3. type $ mount /dev/sda1 /media/tmpdir to mount system
  4. type $sudo gurb-install --root-directory=/media/tmpdir/dev/sda . And no error report means you are almost there.

Attention: sda here is not sda1

  1. Reboot without LiveCD and boot Ubuntu first to update grub with $ sudo update-grub2
  2. Enjoy windows and Ubuntu.

Test sucessfully in win7, win8, win10.

Git SSH Key使用总结

最近频繁使用SSH Key,所以写一篇文章做个小结

Clone with SSH or HTTPS

首先我们知道,在GitHub上使用git clone时,有两种方式,一个是SSH,一个是HTTPS。那么这两者有什么区别呢?

  • 使用HTTPS clone对初学者来说会比较方便,因为只需要复制HTTPS URL然后到git Bash里面直接用clone命令克隆到本地就好了,但是每次fetch和push代码都需要输入账号和密码,这就是HTTPS方式的麻烦之处。
  • 使用SSH clone需要在克隆之前先配置和添加好SSH key。也就是说,如果你想要使用SSH clone的话,你必须是这个项目的拥有者。否则你是无法添加SSH key的,另外ssh默认是每次fetch和push代码都不需要输入账号和密码,如果你想要每次都输入账号密码才能进行fetch和push也可以另外进行设置。

如果你没有配置SSH Key就通过ssh使用git clone命令,那么你会看到一下提示:

Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

所以需要生成SSH key并且在github中设置才可以顺利使用SSH clone

查看你的电脑是否已经生成了SSH key

在git bash中执行以下命令

$ cd ~/.ssh     // 进入根目录下的ssh文件夹
$ ls                    // 查看目录下文件

如果没有密钥则不会有ssh文件夹,有则备份删除

如果目录下存在id_rsaid_rsa.pub则说明已经存在SSH密钥

生成SSH密钥

那么如果不存在,则需要我们配置生成SSH key

$ ssh-keygen -t rsa -C "guoxu@bupt.edu.cn"

之后的三个提示直接默认回车就好,接着你会看到

Your identification has been saved in /c/Users/GuoXu/.ssh/id_rsa.
Your public key has been saved in /c/Users/GuoXu/.ssh/id_rsa.pub.

也就是得到id_rsaid_rsa.pub,并且之前的路径就是你的SSH密钥的位置

还会提示Key fingerprintkey's randomart image(这里不是本文重点,有兴趣的小伙伴可以自己研究一下)。

以上说明你的SSH密钥已经成功生成。

配置SSH Key

最后你可以使用命令cat ~/.ssh/id_rsa.pub来查看你的SSH Key,并且将它复制到github的SSH key页面中即可。

如果这也算创业——奔奔波波小半年

“五点起床,换好西服,在夜色中搭上第一班地铁前往良乡答辩。一路上梦梦醒醒,嘴里念着答辩词。直到结束鞠躬,我悬着的心才放下。”

事情得从去年校庆说起,当时报名了优秀校友创业沙龙。当时整场沙龙听下来,我不停地在记录我觉得对我有启发的点子,但对创业还是没有一个清晰的概念。

接着就到了今年四月。当时正是大创申报项目的时期,我有幸找到了隔壁宿舍的一名志同道合的同学,当时的想法还只是和他一起组个队做个大创。当时我俩在自习室研究了一晚上做什么,最后的结论是:idea已经想好了,就差一个实施的团队。听起来很像“就差一个程序员系列”。是的,故事以失败告终,我和那位同学最终没有合作起来去组建团队并去实施我们的想法。但我并没有就此放弃,我一直保持对校内创新创业咨询的关注,直到有一天我发现一个学长(也就是我后来的Leader)在招能写前端的大二小伙伴,恰逢当时我处在前端入门,看学长要求好像也不高,于是抱着试一试的心态联系了学长。于是故事才真正开始。

我得到了认同并且加入了团队,进一步了解了我们团队的项目之后,我的第一感受是,这个项目真是太棒了,我怎么就没有想到呢?于是我在学长的带领下学习、工作了一个月,接着迎来了五月的大创展。我做了三件事:
1.做了一个宣传我们产品的H5应用;
2.代表我们团队上主席台宣讲;
3.坚守在展区为老师同学介绍我们的项目;
现在看来当时做的三件事是小事,但对那时的我来说已经是意义非凡了,就像是发现了新大陆,就像是找到了除了前端之外另一件让我充满热情的事。在那之后我对团队的项目有了更深刻的理解,但还是对创业没什么概念,因为毕竟那只是一个创新为主的项目展。

之后的暑假,我先是留校参与了团队项目的策划与推进,后又代表团队参加诺基亚企业游学营。这个夏天值得纪念的是不仅仅是在游学营学到的创业基础;还有一路相伴优秀的学长学姐、成功企业家的言传身教以及深入诺基亚内部去了解、学习、感受企业文化;以及我见证了项目进展的成巨大阻力、成与败,这真正让我明白什么叫“创业维艰”。

对于在校大学生来说,校园为我们提供温馨的学习环境;但同时也隔断了我们和社会。好吧其实我更想说的是隔断了市场,因为对于你想做的项目,首页市场调研是必须的;另外你需要通过市场了解一个行业的需求以及未来。有一门创业选秀课的老师说,不管是低年级还是高年级的同学,都存在的一个普遍问题就是缺乏市场思维。在我理解来就是没有接触市场,主观臆断一个项目的背景、一类用户的习惯、一个产品的未来。我自己深有感触,当我接触了市场才感原来我想的是这样,而事实是那样。

创业,若是侠义地定义,那我们都远谈不上创业。而当你的项目越是往后发展,你越能了解创业维艰。创业成功也不是什么四个要素就能总结的,只能说创业确有其方法论,但事在人为,最后能决定一个好项目的还是你的团队,以及你的决断和你的个人能力。对创业或是项目本身而言,也许最好的状态是专注于项目本身,把创业的野心放在心底。当你的个人能力、你的项目、你的团队足够成熟时,一切都会随之而来。正所谓创业维艰,我们尽人事,剩下的交给上天。

言の葉の庭——一场雷雨的悸动

隐约雷鸣 阴霾天空 但盼风雨来 能留你在此
隐约雷鸣 阴霾天空 即使天无雨 我亦留此地

动画很短,不过50分钟,但看下来每一分钟都叫人难受。从开场便是叫人压抑的梅雨和焦躁的氛围。然而我们却相遇与此——雨中的庭院;在压抑的雨中身边是充满了生命的绿,叫人眼前一亮。

言叶之庭,直译为中文即言语的庭院。一个是只在雨天早上翘课的学生,而另一个是只在雨天早上翘班的老师,两人却在雨天“邂逅”并在此开始了心的交流。整部动画剧情简单,平淡,但我看来十分揪心。

一个是15岁的男生,而另一个是27的女人;
一个是学生,一个是老师。
虽然男主角提到自己年仅十五岁,但影片中传递的形象是一个干净的男人;
相应地,女主说自己已经二十七岁,但内心却更像是一个十五岁的女孩。

孝雄最后与女主不仅是异地恋,还在身份、年龄上有差别。而他虽然只是一个中学生,但他知道如果他什么都不做那什么进展都不会有,所以他在假期里打工,也坚持着自己的梦想,并通过为女主做一双鞋的方式来表达自己的心意。其实我们很难想象一个十五岁的男孩爱上一个大自己十二岁的女老师,但我想说的是对一个尚年幼的男生来说,与同龄女生恋爱和与比自己年长的女生恋爱在心理上是有很大不同的。和同龄女生的恋爱,显得轻松、甜蜜、好似无忧无虑,一种“在最美的年华遇到你”的感觉;而和一个比自己年长的女生恋爱,男生会去思考怎样努力去进展,而不是仅仅沉浸在感情里什么都不做,那样的话什么结果都不会有。我想这正是这部动画的揪心之处。

片尾曲《Rain》和《One more time》一样贴合影片主题,在BGM出现的时候会有一种正正好的感觉,所有的情绪也都被抑制得正好,不盈不满。

平淡无奇,回味悠长,真叫人难受。

也许值得纪念的小事情

2017.1.20 01:28

再有半天就到家了,离开学校前我一直在想到底什么东西忘了带,最后也只是因为太冷回去再拿了一副手套;

直到今天下午睡醒想的第一件事还是考试,回家的兴奋也消磨殆尽,我才明白我还没准备好回家。

又是一年,忙碌着兴奋着也疲惫着失败着,只是让人更奢望平淡。

离开家的327天,我真的想你们。

2017.1.14

最近一周都是好天气,很想骑车,很想回家。

这个学期忙忙碌碌最大的一个收获是,学会了抓主次。

2017.1.11

看得见差距,看得见未来

 

2016.11.20

二〇一六年冬,京城初雪。

2016.11.14

2016.11.12
今天实习的时候来了一群小朋友还有他们家长来参观。
我在想在我这么小的时候,爸妈是不是也这么年轻貌美。

2016.11.10
经过深思熟虑我退出了团队。
量力而行,去做自己喜欢的事情。

2016.10.29
去超市买了土豆番薯白萝卜排骨鸡蛋,也算是改善伙食,也可以说是准备过冬吧哈哈哈。

2016.10.29
早晨五点起床在夜色和睡意中乘了三个小时的地铁到房山区参加决赛答辩。
一路睡着背着答辩稿,结束的一刻如释重负。