吃完饭,洗过碗,开始第一天的活动。

今天的复习内容最轻松,因为是基础中的基础。主要涉及C语言的编译器、语法关键字、运算符、变量及数据类型。

编译器

C语言在Linux上的编译器:GCC

编译tips:使用GCC在64位电脑上编译32位程序

1
2
3
4
5
6
gcc -m32 -o test test.c

#先要安装build-essential module-assistant gcc-multilib g++-multilib

apt-get install build-essential module-assistant gcc-multilib g++-multilib

C语言在Windows上的编译器:CL.EXE
Windows上的集成开发环境,通常是Visual Studio,目前最新的已经是VS 2019版本了,与早些年不同的是,VS Community版本目前对个人是免费的。
但是因为一直以来的习惯,我还是习惯用VC6.0作为我的Windows C语言开发环境。编译连接仍然采用CL.EXE和LINK.EXE,以及NMAKE.EXE。

基本的编译语法

以Hello World为例,代码如下:

1
2
3
4
5
6

int main(){
printf("Hello World\n");
return 0;
}

Linux(Debian)下的编译过程
gcc -o helloworld helloworld.c

Windows下使用CL.EXE进行编译

1
2
cl.exe /c helloworld.c
link helloworld.obj /LIBPATH:C:\Tools\Binary\VC++6.0\VC98\Lib\

这里C:\Tools\Binary\VC++6.0\VC98\Lib\是我的VC6路径,并且执行cl和link需要将程序路径加入到环境变量。

语法关键字

1
2
3
4
5
6
7
auto  break case  char  const  
continue default do double else
enum extern float for goto
if int long register return
short signed sizeof static struct
switch typedef unsigned union void
volatile while

部分关键字含义

  • continue 结束当前循环,开始下一轮循环
  • extern 声明变量或函数是在其它文件或本文件的其他位置定义
  • goto 无条件跳转语句
  • register 声明寄存器变量
  • typedef 用以给数据类型取别名
  • volatile 说明变量在程序执行中可被隐含地改变

运算符

基本运算符

加减乘除、取模、自增、自减: +,-,*,/,%,++,–

赋值运算符

1
2
3
4
5
6
7
8
9
10
11
12
=:简单的赋值运算符,把右边操作数的值赋给左边操作数    C = A + B 将把 A + B 的值赋给 C
+=:加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 C += A 相当于 C = C + A
-=:减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 C -= A 相当于 C = C - A
*=:乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 C *= A 相当于 C = C * A
/=:除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 C /= A 相当于 C = C / A
%=:求模且赋值运算符,求两个操作数的模赋值给左边操作数 C %= A 相当于 C = C % A
<<=:左移且赋值运算符 C <<= 2 等同于 C = C << 2
>>=:右移且赋值运算符 C >>= 2 等同于 C = C >> 2
&=:按位与且赋值运算符 C &= 2 等同于 C = C & 2
^=:按位异或且赋值运算符 C ^= 2 等同于 C = C ^ 2
|=:按位或且赋值运算符 C |= 2 等同于 C = C | 2

逻辑运算符

1
与或非:&&,||,!

位运算符

1
与、或、异或、取反、左移、右移:&,|,^,~,<<,>>

杂项运算符

1
2
3
&    返回变量的地址
* 指向一个变量
? : 条件表达式三元运算符

变量及数据类型

基本类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
整数类型:
char 1 字节 -128 到 127 或 0 到 255
unsigned char 1 字节 0 到 255
signed char 1 字节 -128 到 127
int 2 或 4 字节 -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
unsigned int 2 或 4 字节 0 到 65,535 或 0 到 4,294,967,295
short 2 字节 -32,768 到 32,767
unsigned short 2 字节 0 到 65,535
long 4 字节 -2,147,483,648 到 2,147,483,647
unsigned long 4 字节 0 到 4,294,967,295

浮点类型:
float 4 字节 1.2E-38 到 3.4E+38 6 位小数
double 8 字节 2.3E-308 到 1.7E+308 15 位小数
long double 16 字节 3.4E-4932 到 1.1E+4932 19 位小数

枚举类型

可以在定义枚举类型时改变枚举元素的值:

enum season {spring, summer=3, autumn, winter};

没有指定值的枚举元素,其值为前一元素加1。此例中spring的值为0,summer的值为 3,autumn 的值为4,winter 的值为5。

三种写法

  1. 先定义枚举类型,再定义枚举变量
1
2
3
4
5
6
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;

  1. 定义枚举类型的同时定义枚举变量
1
2
3
4
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
  1. 省略枚举名称,直接定义枚举变量
1
2
3
4
enum
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;

引用枚举类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

enum DAY {
MON=1, TUE, WED, THU, FRI, SAT, SUN
};

int main() {
enum DAY day;
day = WED;
printf("%d",day);
return 0;
}

应该找点让自己开心的事情做。

C语言是我进入计算机领域学习的第一门语言。可惜工作这么多年,早已忘的支离破碎,对链表、数据结构乃至系统编程的知识,早已经还给老师了。这对今后的学习是非常不利的。所以计划从今天开始,抽空花30个晚上,每晚花1~2个小时的时间复习C语言,尽量保证连续。

我的复习会比较跳跃,这个系列的文章,也仅适合作为个人的技术笔记,不太适合作为入门资料进行参考。

我可能会在文章中提及一些调试、算法以及工程方面的技术,相信其中有些内容对搜索引擎来说会是一个比较好的长尾关键词,这样也给一些编程过程中遇到问题的朋友一些参考。本着少废话的原则,尽量避免探讨过于简单的技术。否则可能会沦为小白记事本,反而容易误导网友。

暂时给自己拟定了以下复习计划,30个夜晚主要这样安排(后续可能根据实际情况有所调整):

第一夜:编译器、语法关键字、运算符、变量及数据类型
第二夜:函数、作用域、预处理和头文件
第三夜:指针和数组
第四夜:存储类型、结构体、链表
第五夜:C语言标准库、错误处理和调试、输入输出
第六夜:内存管理、读写文件、管道
第七夜:线程、多线程
第八夜:进程、多进程
第九夜:C语言常见的Linux系统调用
第十夜:C语言常见的Windows系统调用
第十一夜:在C语言中使用内联汇编
第十二夜:使用C语言探索堆栈
第十三夜:网络编程1-网络协议及其数据结构
第十四夜:网络编程2-Socket通信
第十五夜:网络编程3-常见的应用层协议
第十六夜:编写一个Linux的服务
第十七夜:编写一个Windows的服务
第十八夜:C语言动态链接与静态链接
第十九夜:编写一个Linux用户态Trojan
第二十夜:编写一个Windows用户态Trojan
第二十一夜:Linux内核编程1-内核源代码分析
第二十二夜:Linux内核编程2-实现一个内核模块
第二十三夜:Linux内核编程3-实现一个块设备驱动
第二十四夜:Linux内核编程4-实现一个字符设备驱动
第二十五夜:Linux内核编程5-实现一个内核Trojan
第二十六夜:Linux内核编程5-在Linux内核中瞎搞
第二十七夜:Windows内核编程1-Windows内核初探
第二十八夜:Windows内核编程2-Windows驱动编程研究
第二十九夜:Windows内核编程3-在Windows内核中瞎搞
第三十夜:学习总结

真是一个宏大的计划,甚至不知道自己能不能完成,有点期待。

希望可以自律、坚持地完成下去。

参考资料:

Linux kernel下的内核socket编程
Linux系统编程

在看过新海诚的《君の名は。》之后,感动的同时,非常喜悦。
我曾在千与千寻这篇文章中,写过宫崎骏成长的环境,简单表明了,时代造就大师这一观点。

新海诚,就是让人感到他是日本漫画在宫崎骏之后又一位大师,为这个世界带来满满诚意。

我说过我们老了以后不会无聊,事实上在我们还如此年轻的时候,就已经不无聊了。

在豆瓣看了这样一篇关于天气之子的影评,自觉表达功力粗浅,看到这样字字珠玑的影评,满脑子只有刘关张结拜时张飞的那句”俺也一样“,带着一种热泪盈眶。

文艺评论并不是我的特长,每次写所谓的影评,我常常容易看起来跑题,不怎么提及影片本身,而更多的出离作品,结合我自己对生活和艺术的主观感受,去品味作品的灵魂。

日本比我们更早进入繁荣时期,曾经的日本年轻人比我们更早地遭遇到经济发展、社会进步所伴随的迷茫与困惑。他们的如今,折射出我们的今后。

我一直将日本这个国家视作一个有趣的观察对象。他们和我们拥有同源的东亚文化,可以追溯到盛唐时期,甚至在某些方面,比我们保存的更完好,例如建筑、礼仪、料理等等。在亚洲的民族当中,日本一直是一个学习能力很强的民族。在古代,他们向中国学习先进的文化,并良好地继承和发扬。在近代,他们从欧美学习机械和电子,并在20世纪末创造了空前的经济辉煌。这无疑是亚洲班里一位踏实的尖子生。

为什么观察日本?可以认为日本就是东亚文明升级过程的一个小型实验场。在这个实验场里可以看到东西方文化的交融、碰撞,传统文明与现代文明的对立、统一,而这些现象,放在我们的社会同样适用。社会在发展过程中,很多事物当然应该以史为鉴。而如果有一个能够把玩和观测的经验模型,岂不更妙?

我们这代人此时所遭遇的困惑和际遇,也正是日本上一个阶段的年轻人所经历过的。他们也经历过科技的进步、房市的繁荣、股市的爆发,乃至美国的打压。蜡笔小新五岁的时候,家里房贷还剩下30年,美芽喜欢逛商场,广志带回家一台笔记本电脑,一家人偶尔旅行和野餐。这些小民生活的方方面面,如今只不过是换了时间和形态,重演在我们的人生历程中。他们的社会就像是时空隧道传出的一道剪影,让我们提前预知一些事物的发展方向。事实上,由于世界局势发展的不确定性,能透过他们预知的距离也越来越短。我们正在一边观测,一边超越。今天东京街头的年轻人,可能和首尔、洛杉矶、上海的年轻人的思想差不了太多。

漫画有时是对生活的解构和期望。很多在现实中难以如愿的,就去漫画里圆满、去发泄。

看新海诚的《天气之子》,最多的感触是,社会角落中生活的人们,他们眼中的天空,是怎样的耐人寻味。

他们的快乐和痛苦,他们的青春和爱情。他们那些刻骨铭心的记忆,他们那些难以割舍的爱人。

社会的条条框框,约束人生的方方面面,将棱角分明的少年,磨成世故圆滑的大人。

习惯了资本的游戏,舍弃了纯粹和天真。既抱怨着透不过气的生活,却又践踏着自由的土壤。

厌恶荒诞戏谑的现实,又更卖力地表演着丛林法则。没有放弃一切的勇气,却还觊觎灿烂美好的晴天。

这解释了为什么,年轻的晴女拥有了治愈东京的神力,也愿意抛弃,只选择和所爱的人在一起,守望朝夕。

新开辟了一个博文分类,社会
分类叫做社会,但是却不怎么敢聊社会。至少有些话题我是不敢聊的。
但是今天,还是来随便聊两句,作为这个系列的开篇(不保证有后续)。

从某厂“不让”注销说起

如果你是一位这厂用户并且你能幸运地找到以上页面,你也许会有知乎上这个问题一样的困扰。

为什么大部分的中国互联网公司,都把注销功能做的不尽如人意甚至压根不做呢?这个问题实在太深刻,深刻到令我无从解读。

其实根据工信部《电信和互联网用户个人信息保护规定》第九条,用户完全有注销帐号的权利。但很多互联网公司都没有为用户提供这项权利。

第九条 未经用户同意,电信业务经营者、互联网信息服务提供者不得收集、使用用户个人信息。

  电信业务经营者、互联网信息服务提供者收集、使用用户个人信息的,应当明确告知用户收集、使用信息的目的、方式和范围,查询、更正信息的渠道以及拒绝提供信息的后果等事项。

  电信业务经营者、互联网信息服务提供者不得收集其提供服务所必需以外的用户个人信息或者将信息用于提供服务之外的目的,不得以欺骗、误导或者强迫等方式或者违反法律、行政法规以及双方的约定收集、使用信息。

  电信业务经营者、互联网信息服务提供者在用户终止使用电信服务或者互联网信息服务后,应当停止对用户个人信息的收集和使用,并为用户提供注销号码或者账号的服务。

  法律、行政法规对本条第一款至第四款规定的情形另有规定的,从其规定。

也有一些公司为用户提供了“注销”这项功能,但注销删除是有区别的,我相信用户选择注销帐号,更多的是希望能够从数据库中将自己的信息删除。然而从程序员的角度来看,对数据库执行一个删除操作,显然要比增加一个删除标记字段的风险大的多。尤其是对于现在靠用户数据卖钱的公司来说,删除用户,那就是在割自己田里的韭菜苗,挖韭菜根啊。何况,工信部的规定,也并没有提到要删除,只说需要提供注销的功能。你要注销,可以,把你的账号锁定,手机号释放,禁止你登录,标记为注销。

更何况,现如今很多公司都提倡什么微服务、数据中台,本来一个MySQL就能搞定的数据,非要在Redis里放一点,Mongo里面放一点,ES里面放一点,这就导致如果要真的从系统中完整删除一个帐号,远比想象的要复杂,数据和业务之间可能会有错综复杂的裙带关系。你要问这些公司为啥要这样做?很简单,员工要吃饭,上司要成绩。不上新架构新业务,经费怎么花?奖金谁来拿?从老板层面而言,就更是如此。养着一帮程序员,工资又那么高,不让他们做点事情压榨压榨,自己岂不是亏了。可是业务是固定的,用户也是稳定的,让他们做啥好呢?那就什么新做什么吧,这阵子大数据新,就上大数据,过阵子AI火,那就用AI,区块链概念好,那就玩区块链……

互联网圈里很多人有个臭毛病,就是代码也许写不了几行,但是吹起NB绝对是最靓的仔。

互联网公司个个看起来高大上,可是大部分不过是CRUD功能堆砌起来的信息垃圾堆而已。如果不清楚什么是CRUD,就这么跟你说吧,CRUD说白了就是基础的增删查改(Create,Retrieve,Update,Delete)。

以SNS网站为例,其基础功能从逻辑本质上来看,无非就是信息创建、信息修改、信息索引,就是增删查改。并没有什么高大上,反倒是业务庞大了以后,雇了太多活儿糙的程序员,导致部门臃肿,架构复杂,业务更加垃圾。

说到这里,有些代码孔乙己可能会出来杠。算法和架构的事,能叫CRUD吗?紧接着,便是分布式缓存、后端渲染、大数据、机器学习……写字间里又传来一阵快活的笑声。

我根本不想杠,写博客本来就图个乐。

不过话说回来,也不能小瞧这些创造垃圾的公司,他们割起韭菜可是很有水平的。不信你看,中文互联网公司,盈利的高招儿,我来悉数一下:

做文档的公司,放贷款;
做手机的公司,放贷款;
做社交的公司,放贷款;
做视频的公司,放贷款;
做搜索的公司,做医疗;
以上公司,也偶尔插播植发广告。

美名其曰运营。实际上是杀猪。在他们眼里,用户就是猪,也许有的时候,用户还不如猪。

聊聊互联网自由

前面说到互联网公司的问题,不得不进一步思考。互联网发展至今,是否还有人记得它的初心?互联网究竟是解放了人类,还是为人类制造了新的枷锁?

互联网最开始,人们希望的是拥有自由、开放、共享的互联网,让人们可以在浩瀚的数字海洋里畅快地傲游。可如今,TikTok被威胁,让人甚至感觉到一种魔幻。曾经我们以为大洋彼岸的那块土壤,可以繁衍出自由的互联网。可如今再看,所谓自由不过也是游戏规则制定者嘴里的说辞罢了。

放眼整个互联网世界,如今似乎正在经历一场浩劫。欧洲、俄罗斯,都在考虑封锁自己国家的互联网。真不知道今后,还有没有能够让全人类互相连接甚至连接一切的互联网。想起圣经里面提到的,上帝为了阻止人类建造通往天堂的巴别塔,把人类分散在世界各地,让他们说不同的语言,从而无法协作。而曾经人们一度相信互联网可以让全人类产生紧密的联系,可以促进一切的发展。然而事实上,互联网却只沦为了少部分人的舆论场,投机分子的势利场,资本家们的养猪厂,犯罪的温床。

虽然也有过奇妙的一幕,就如维基解密棱镜门、巴拉拉文件、各种门。微博也曾经为寻人、破案、反腐带来了一些不可思议的效果。

可互联网世界更多的却还是充斥着一种难以名状的混沌。

这一切因果,究竟是互联网的罪恶基因在作怪,还是人类的秉性使然?

是否自由就意味着混乱?是否以人类的本性,根本就不配拥有互联网这样的观照之境来普渡众生。

什么时候互联网的世界,才可以有一片纯净的天空。人类可以利用互联网,传播真正有价值的信息和言论,透明而严谨的真相,而不是140个字的废话,声色犬马。

也许需要先提高全体人类自身的认知水平,才能逐渐实现这一切。也许,没等到提高全体人类的认知水平,这一切就已经毁灭在黎明前夕。

总之,今天我已经选择注销大部分社交帐号,选择在浩瀚的数字海洋里,自闭成为一座孤岛,就像这个网站一样。

选择阅读更多纸质书籍,投入于更多经典,沉下心来,去踏实研究这世间的学问。

我相信,即使是一艘小船,也可以纵横四海,阅尽千帆。

海船

2020/07/26摄于 南京-大胜关

很久没有写字了,但却从未停止思考。这么一方小天地,自是无人问津,可以畅快表达。

永恒的事物,必要时间去证明它的价值 – 或是它的荒诞。

思考太多却很少见诸笔端的主要原因有三:

一是不够自信,一直处于自我怀疑之中;
二是读书太少,更加不敢开口,怕暴露智商;
三是不敢胡说,文字表达天生存在缺陷,开口即是错。

在我自己开辟的一方赛博领土之上,我倒是愿意说一些莫名其妙的真话。但最好也是猥琐到让人不能轻易看懂,自己也安全。

今天就来谈谈,很久以来,一些一直在思考却从未有结果的事情。我想很多我早已想通的道理,而世界却未必明白。

所以我将它写下来,孤独的思想者,把一切苍白的辩驳都交给时间。

眼前的光景,是荒唐的人间。世界观没来得及稳固就被颠覆的感觉,不知道是否有人能够体会。

我们的生活,B站、抖音,歌舞升平,一浪高过一浪。生活仿佛从未发生变化甚至快要高潮一样,而这正是当下最该警惕的地方。

不禁想回忆起,从什么时候开始觉得生活变得逐渐不一样?我觉得是从2012年。

混沌中心

混沌是什么?混沌是无法描述的,就如此刻我想诉说的事物,它无法被琢磨,无法被找寻,无法被把握。

但能清楚的感受到它的存在。更进一步的,是能感知到,它将去向哪儿。

我们身处混沌的中心,眼前充斥着一切迷雾,混沌假以掩饰,令我们亦步亦趋。

我们的生活,如今被互联网所支配。而互联网是一个无法停止的事物,一旦启动,就必将改变眼前的一切。

而有一些价值观,需要被表达,也是此文的意义。

可能有些人,看到这里,就不再继续读下去了。这也正是每当想要对这个世界阐述一种立场时,最悲观的地方。

黑客精神

黑客在看待一个问题时,首先是质疑。如果想要知道一道上锁的门是否可靠,只需要推敲即可。记住,质疑,再然后是推敲。

世上之事,大抵如此。从SQL注入,到人生的意义。其实世上之事,大都经不起推敲。

地球上所有的信息系统,都有漏洞。甚至可能连数学理论本身都有漏洞。如果你认为printf(“hello world\n”)这样的代码不会有漏洞,请看看射线导致磁盘、内存位反转的案例。类似这样的,甚至更加古怪的问题,人类黑客,可能永远也无法发现它。而很多时候逻辑深处的漏洞,甚至比物理漏洞还要隐蔽。之所以常人觉察不到,仅仅是因为认知和格局还无法辅佐我们抵达。

可悲的是,如今大部分具有黑客思维的人,所从事的工作,竟然是在给这个世界上最愚蠢的程序猿们开发的CRUD系统寻找所谓的安全问题!更可悲的是,很多在质疑和推敲方面具有良好潜质、良好的思辨能力的选手,竟沉迷在这样的工作当中无法自拔,自我满足。

黑客生存的意义,绝不应该局限在给信息系统寻找漏洞这件经不起推敲的事情。当好不容易具备了与别人不一样的怀疑视角,一定不要把这种能力埋没在和傻瓜比数数,以及指导他们做作业这些无聊事情上。而是应该去研究金融、经济、Politics、管理。当然,如果你的脑核足够富余,哲学和数学更是个不错的选择。

只提出愿景,而忽视现实,是非常惹人讨厌的。你可能会说,黑客也是人,黑客要吃饭,养家糊口,就必须去做一些很傻的事情。其实这是经不起推敲的,看透一切事物的本质,便知道物欲也是虚无。穷且益坚,求真务实,就成为了一个黑客该有的​追求。

其实,只要能理解,这个世界上,大部分事情,都经不起推敲的​道理,就不会再去追求物质。

​​就说金钱吧。在以黑客思维去看待地球文明时,货币系统只各个互斥的群体为了内部耦合与外部协作而构建出的一套​算法罢了。货币、贵金属、古董,乃至一切等价物,都只是对​价值结构体的引用罢了。

个体的贫穷和富有,取决于这套算法的​实现逻辑。掌握了这套算法,未必能实现富裕。有commit的权限和编码的水平,兴许倒可以实现利益最大化。

但是跳脱出这个系统,才是黑客精神。仅仅沉迷在这套系统之间,还是​没有意义。

最近的这几个VirtualBox版本(6.1.4、6.1.6、6.1.8)比以前多了一些变化,主要体现在Guest Additions上。

在6.1.4、6.1.6的版本里,曾经遇到过虚拟机和宿主机(Guest and Host)之间不能共享粘贴板(Clipboard)的bug,以及Windows 7、Debian10的Guest机器无法全屏的Bug。

之前的解决方法是,在 VirtualBox官网上下载Virtualbox 6.1.2版本的Guest Additions ISO,挂载并且安装ISO镜像中的VBoxLinuxAdditions.run文件后,即可解决这些问题。

但在今天的6.1.8版本的Release Changelog中,提到已经解决了多个这样的Bug,于是试试运气,结果遇到这样的问题:

1
VboxClient: The parent session seems to be non-X11. Exiting...

这里分享我在Windows 10 Host,Debian 10.0 Guest上的解决方法:

先注销当前用户:

再在登录的时候选择X11选项:

即可解决。

0x00 前言

Rails 6.0 发布已经有一段时间了,之前没有什么项目可以练手,最近总算遇到可以使用Rails 6开发的场景了。Rails 6中新增了一些功能和特性,有一些内容官方文档里并没有写的很具体,所以在摸索的过程中也遇到了一些坑点。这里以一个新工程从头到尾的构建,来简单记录在Rails6中使用jQuery和Bootstrap的过程。希望能够给新来的同学做个参考。

编程和码字的水平有限,如有错漏敬请指教,也请多包涵!下面就开始吧。

0x01 环境准备

  • 操作系统: Debian 10 ( 4.19.0-8-amd64 )
  • Ruby版本: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
  • Rails版本: Rails 6.0.2.1
1
2
3
4
5
6
7
test@debian:~$uname -a
Linux debian 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64 GNU/Linux
test@debian:~$ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
test@debian:~$rails -v
Rails 6.0.2.1

0x02 创建项目

这里新建一个项目“TestApp”,并在其中建立控制器“Test”和测试方法“test”:

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
test@debian:~$rails new TestApp
create
create README.md
create Rakefile
create .ruby-version
create config.ru
create .gitignore
create Gemfile
...
├─ [email protected]
├─ [email protected]
└─ [email protected]
Done in 59.74s.
Webpacker successfully installed 🎉 🍰
test@debian:~/TestApp$rails g controller Test test --no-stylesheets
Running via Spring preloader in process 22413
create app/controllers/test_controller.rb
route get 'test/test'
invoke erb
create app/views/test
create app/views/test/test.html.erb
invoke test_unit
create test/controllers/test_controller_test.rb
invoke helper
create app/helpers/test_helper.rb
invoke test_unit
invoke assets
invoke scss
test@debian:~$

创建好之后,修改test页面,添加一个表单和按钮,用于稍后测试Bootstrap。(在执行创建控制器和方法的命令后,Rails已经为我们自动添加了到Test控制器test方法的路由,所以不需要我们再新增路由。)

app/views/test/test.html.erb 代码:

1
2
3
4
5
6
7
<h1>Test#test</h1>
<p>Find me in app/views/test/test.html.erb</p>

<form>
<input id="test" type="text"/>
<button id="test_btn">点我</button>
</form>

启动Rails服务,访问http://localhost:3000/test/test:

1
2
3
4
5
6
7
8
9
10
11
test@debian:~/TestApp$rails s
=> Booting Puma
=> Rails 6.0.2.1 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.1 (ruby 2.6.5-p114), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop

此时应用已经创建成功。

0x03 添加jQuery和Bootstrap库

这里采用yarn作为Javascript包管理器。在TestApp目录中运行bin/yarn,如果出现以下内容,说明yarn没有安装:

1
2
3
test@debian:~/TestApp$bin/yarn
Yarn executable was not detected in the system.
Download Yarn at https://yarnpkg.com/en/docs/install

安装方法在这里, 以当前使用的Debian 10为例,安装的方法是:

1
2
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list

安装好yarn之后,就可以用yarn添加jQuery包和Bootstrap包:

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
test@debian:~/TestApp$yarn add jquery 
yarn add v1.21.1
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > [email protected]" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning "webpack-dev-server > [email protected]" has unmet peer dependency "webpack@^4.0.0".
[4/4] Building fresh packages...

success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ [email protected]
info All dependencies
└─ [email protected]
Done in 9.98s.
test@debian:~/TestApp$yarn add bootstrap
yarn add v1.21.1
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > [email protected]" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning "webpack-dev-server > [email protected]" has unmet peer dependency "webpack@^4.0.0".
warning " > [email protected]" has unmet peer dependency "popper.js@^1.16.0".
[4/4] Building fresh packages...

success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ [email protected]
info All dependencies
└─ [email protected]
Done in 13.33s.

由于Bootstrap还需要基于popper.js,不装的话会报依赖错误,所以安装一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
test@debian:~/TestApp$yarn add popper.js
yarn add v1.21.1
[1/4] Resolving packages...
warning [email protected]: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1
[2/4] Fetching packages...
info [email protected]: The platform "linux" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > [email protected]" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning "webpack-dev-server > [email protected]" has unmet peer dependency "webpack@^4.0.0".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ [email protected]
info All dependencies
└─ [email protected]
Done in 11.78s.

安装的执行结果:

因为众所周知的原因,网速慢的同学就尴尬了,这里可能要等很久,所以你需要选一个科学一点的方式。

此时查看TestApp/node_modules目录,所需的前端库已经添加好了:

1
2
3
4
5
6
7
test@debian:~/TestApp$ls node_modules/jquery/
AUTHORS.txt bower.json dist external LICENSE.txt package.json README.md src
test@debian:~/TestApp$ls node_modules/bootstrap/
dist js LICENSE package.json README.md scss
test@debian:~/TestApp$ls node_modules/popper.js/
dist index.d.ts index.js.flow package.json README.md src
test@debian:~/TestApp$

0x04 使用Bootstrap

跟Rails5有所不同的是,Rails6采用webpack打包的方式,把需要打包的资源统一放在一个文件里(Rails6之前是采用Gemfile的方式引入第三方库,再通过Asset Pipeline汇聚)。

于是在安装好所需的前端库之后,就需要在app/javascript/packs/application.js中先引用它:

以Bootstrap为例,在其中添加import 'bootstrap'引入语句:

与此同时还需要在application.scss中引入Bootstrap的CSS样式表:

app/assets/stylesheets/application.scss文件中添加@import "bootstrap/dist/css/bootstrap";


2020/05/28 Patch

纠个错,如果想要通过@import "bootstrap/dist/css/bootstrap";的方式引用bootstrap相关的CSS,需要把app/assets/stylesheets/application.css文件重命名为app/assets/stylesheets/application.scss
如果直接使用app/assets/stylesheets/application.css的话,那么采用如下方式来引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
* File: app/assets/stylesheets/application.css
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require bootstrap/dist/css/bootstrap
*= require_tree .
*= require_self
*/

Ending Patch


接着继续修改app/views/test/test.html.erb文件中的代码,添加相应的CSS类来测试Bootstrap是否已经引入成功:

1
2
3
4
5
6
7
8
9
<h1>Test#test</h1>
<p>Find me in app/views/test/test.html.erb</p>

<form>
<div class="form-group">
<input id="test" type="text" class="form-control"/>
<button id="test_btn" class="btn btn-success">点我</button>
</div>
</form>

启动应用,再次访问测试页面:

虽然界面有点丑,但是从渲染效果来看,Bootstrap已经成功引入了。

0x05 使用jQuery

继续修改app/javascript/packs/application.js,添加用于测试jQuery的代码:

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
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")


// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

import 'bootstrap'

$(document).on('turbolinks:load', function(){
$("#test_btn").click(function(){
alert($("#test").val());
});
});

保存并运行,刷新https://localhost:3000/test/test页面,发现添加的代码无法执行,控制台中有报错:

1
2
ReferenceError: $ is not defined 
application.js:21

这是因为jQuery库也需要引入一下,但是引入的方式有些不同,并不是在页面中直接引入,而是需要在config/webpack/environment.js中添加以下引入代码:

1
2
3
4
5
6
var webpack = require('webpack');
environment.plugins.append( 'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
})
)

通过声明一个全局的导出,就可以在全局的JS代码文件中使用”$”符号了。

刷新并再次访问,代码能够运行,控制台也没有再报错,说明jQuery已经成功集成:

另一种方法

还有一种方法是通过在JS文件按中使用import $ from 'jquery'来使”$”符生效,但是这样比较繁琐,需要在每个JS文件中出现,所以不再介绍了,当然,也提供一下详细的代码参考

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
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")


// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

import 'bootstrap'
import $ from 'jquery' // 在每个JS文件中加上这一行,也可以替代声明全局变量。

$(document).on('turbolinks:load', function(){
$("#test_btn").click(function(){
alert($("#test").val());
});
});

0x06 总结

在网上主要参考了这篇文章。Rails 6中的变化还是挺大的,不知道webpack会不会真的成为Rails的未来,感觉之前使用coffee script来写JS的同学不是很多,但是我倒是已经非常习惯于使用它来开发前端功能了。

但是想必Rails的先驱们有着他们更成熟的考虑吧,那就一起继续探索好了。

物物而不物于物,则胡可得而累邪!

《庄子·外篇·山木第二十》

庚子年这倒霉病毒的事儿,就不多言了。受此影响,正月里,神州大地的人民,都在家中宅着,用最简单的方式为祖国做着贡献。我自然也不例外,只不过我是个闲不下来的人。虽然平日里我就比较宅,但是按照计划,正月我至少也是要走动走动的。其实若是完全依我自己,我肯定宁愿在家宅着,毕竟守寂淡泊才是我的志趣所在,走亲访友这根本不是我的爱好。只是要考虑家人感受,所以不得不应付罢了。

在家我自然也不会闲着,一早就想要做的事情就是把自己的东西好好整理整理,苦于一直没有时间和思路。这次正好,有了新的思路,也正好有时间,于是在这里谈谈后续的收纳计划。

首先是为什么要收纳。原因很简单,一是家中置物空间有限,不得不收纳。二是,人要时常给自己减轻物质方面的负担,所以要时常扔东西,卖二手,或者是收纳。

我的杂物是很多的,大到健身设备,家电、小家具,小到二极管、电容这些零碎的电子元器件,所以收纳起来相当费事。而我又是一个比较极简和有强迫症的人,所以这就形成了非常鲜明的矛盾。对于不想看到的东西,我的原则就是甩锅。能扔的扔,不能扔的,父母今年正好开着小货车来我这里过年,于是把那些大件的杂物一股脑全让他们拖回到农村老家,老家的地下室、后院,尽可以随便放置,眼不见,则心不烦。但是很多的小物件,就得一一归纳,汇总打包了。

于是我问自己,有什么东西,是十年之内用不到,但又是我不想扔的。

这样一来,就清楚多了。这批物品中,包括到期的保险单、人生的第一枚鼠标,积攒的用来制作特斯拉线圈的铜线,还有用来制作电磁炮的铝管、智能小车上的18650电池组、嵌入式开发板。也许未来十年,我不会有时间去完成那些小制作和小梦想了,但是未来的某一天,希望我有时间,可以再拾起它们。对这些物品,我需要准备打包盒将他们封印,放在一个看不见的地方,等待下一次搬家。

当初在收集和购买它们的时候,对自己的时间,是有着满满的自信的。以为可以无忧无虑,废寝忘食地投入在爱好当中。而现实是,自己既没有无忧无虑的资格,又没有经得住废寝忘食的身体。普通人的精力是有限的,最近几年深深地意识到这一点,于是把自己的领域逐渐收窄,想必,这辈子大部分工作的时间和精力,会扑在软件和互联网领域了,这是我选择的方向。

庄子说,物物而不物于物。我的内心有着太多的物,却不能够物之,这是非常不应该的,也是我心累之根源。

相信在之后不久的日子里,我就要与这些杂物短暂地告别了,就让我将他们尘封在时光机里,在未来的某一个时候再见吧。

身外的杂物,终究是容易收拾的,而心里的杂念,整理还需要时间。什么时候,待我不再物于物,想必才能真的理解庄子。

最近有不少好剧,有时候网速不好追剧太累了,而且有的有广告。看了一下几个主流的视频网站,有不少都还是用的标准的hls协议,没有在此基础上做修改(所以容易导致影视资源泄漏)。用标准hls协议的好处就是我们可以基于hls协议很方便地将影视资源多线程快速下载到本地,既可以流畅观看又可以去广告(部分)。

于是写了一个多线程的m3u8的文件下载器,基于python3纯原生库,安全放心:

代码链接:

https://github.com/Chorder/m3u8_downloader

顺便说一句,m3u8文件挺有意思的,结合ffmepg的缺陷,曾经爆出过播放器任意文件读取漏洞 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-1897 ,但是亲测在浏览器中m3u8文件其实还有更多妙用。感兴趣的童鞋可以进一步玩耍一下。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×