Shawn's Blog

一个伪程序员的伪技术博客

0X00 正文

这篇内容可能是目前为止我所有博客内容里最特别的一篇了,今天不想写什么技术类文章,只是想发发牢骚,说说自己想说但一直没啥机会吐槽的事情。不知道各位有没有那种情况,其实自己是很乐观很开心的一个人,但就是偶尔会突然觉得很累,很烦,很焦虑。这些事情说大可能并不大,只是打个游戏可能某一关打不过去而已;说小可能也不小,甚至跟全国乃至全球数以亿计人口的健康相关。那接下来我就要开始吐槽了,也许会有些负能量,但把自己的「负能量」一股脑输出出来没准就能让自己变得更好呢
hhhhh

tips: 这些内容不分前后顺序、没有主次关系、不一定符合你的看法、甚至你觉得我就是在胡说八道,但我不在乎~

我就想随随便便看个综艺

本来我很早就看今晚80后脱口秀的,虽然我并不是 80
后。也挺喜欢听他们说脱口秀的,不管是现在已经转行的王自健还是后面一直在说的蛋蛋建国什么的。后来 80
后脱口秀就不播了,我也就没再关注过脱口秀了。知道某天偶然间发现了脱口秀大会这么个节目,还挺喜欢看的,就每次看到在更新了就会跑过去看。我一直会给自己的时间安排上学习、娱乐什么的,但是这个节目因为我看起来确实非常快乐,所以只要它更新了我基本上就会把当天的学习计划或者游戏计划都延期,来专门看这个节目。

但是现在这个第五季,就经常在网上看到有人评论说「李诞人不行,就知道复活自己公司的人」「一天到晚就知道说内部梗,不利于脱口秀发展」「比赛有黑幕」这些那些的。我就一个工作学习累了的小小程序员,就想躺在沙发上听听脱口秀,谁
TM 关心李诞复活谁了?谁 TM 关心脱口秀发展了?脱口秀发展的好了我是能多赚钱吗?还是说脱口秀发展不好了会让我爱情事业双受挫?

我就是一个纯纯路人观众,我就想听听好笑的东西让自己笑一笑,虽然我也会想让自己喜欢的演员晋级,但说真的我并不在乎他能拿到什么大王不大王的,只是说晋级了就还能至少再听一场他的演出而已。真不理解这些人一天天的怎么就这么无聊,到处盯着别人的各种细节去看,还要吧儿吧儿的说你。跟你说「脱口秀大会这么黑幕,你居然还看得下去?」「难道只有我一个人觉得这个节目无聊?」。你
TM 看不下去就不看嘛,来逼逼啥;你 TM
觉得无聊就去找点有趣的事情做嘛,管我干啥。我就想在累了的时候笑一笑,结果还要被这种人突然恶心一下。

我就想随随便便打个游戏

本来说我一个从来不玩手游的人,想看看最近的手游都发展的怎么样了,就下载了几个比较火的手游试了试。结果呢,有些游戏一打开就把我当个弱智,整个屏幕都是灰色的,就只高亮一个按钮,旁边写一大堆字,告诉我应该点这里。点了之后又告诉我该点那里、点那里、再点那里。一路点下来我发现已经完成了「新手教学」任务,给了我吧啦吧啦吧啦一大堆东西,但此时的我就是机械的点完了这些按钮,完全不知道他们是干啥的,甚至不知道自己干了啥。。。要不然就是一些竞技类游戏,自己发挥好了可能会被队友坑,自己没发挥好可能会被队友骂,有可能自己和队友都发挥好了但是敌人太强最后还是输了,结果搞得垂头丧气。。。还有些就是整一大堆「日常任务」和「周常任务」,说真的我白天对着工作的
TODO LIST 逐个清理完,晚上回家再对着游戏里的 TODO LIST 逐个清理,就觉得自己很蠢,完全不知道自己为什么这么折磨自己。

我就只是想找个游戏放松放松,目前发现除了主机游戏和部分单机手游之外,想要图一乐就只能是王者这种游戏的纯匹配模式,自己和队友都不在乎输赢而且也没有什么乱七八糟的任务。

我就想随随便便出去逛逛

当时刚开始实习和刚刚转正的时候并没有什么钱可以出去玩,现在虽然也没有啥钱,不过偶尔出去逛逛的预算还是有的。但是现在这个傻逼防疫政策整的,说真的比起疫情我更害怕防疫政策。现在出去玩一趟在不被隔离的情况下,需要首先查询离开当前城市的防疫政策、到达目的城市的防疫政策,然后做核酸检测,还要在核酸检测报告过期之前出发。到了目的地之后又要三天两检七天三检巴拉巴拉的。即使你完全符合了当地的防疫政策,还有可能会被「大数据赋码」给整成黄码。接下来就要到处去咨询和投诉,最后还不一定能解决(真实遭遇)。最后你的游玩结束了,要回到自己的城市,还要看出发和到达两地的防疫政策,回到了自己的城市之后第一时间就会收到短信威胁(真实遭遇),如果不进行三天两检或者七天三检啥的,就又会让你变成黄码。

那如果不出省不出市呢?即使上个班也要检查核酸报告,坐个地铁也要看核酸报告,吃个饭也要看核酸报告。身边也出现过几次因为核酸报告没有准时出来,结果背着包在楼下溜达了半个小时一个小时,等到了核酸报告才进楼上班的;也有出现过因为错过了核酸检测时间,导致第二天没有报告,然后不让进地铁站,最后只能打车十几二十公里去上班的。现在路上看到没啥人的核酸检测点都不由自主的过去排队,用同事的话说就是「巴普洛夫看了会沉默,巴普洛夫的狗看了会流泪」。

当然了最他妈扯淡的是进入餐饮场所不戴口罩还他妈不让你进。我是真的不理解我为什么要戴着口罩进餐厅。

好了我吐槽完了

真的吐槽完了?那肯定是没有的,只是现在已经晚上十一点半了,我打算睡觉了。毕竟如果一直吐槽的话,键盘被敲烂了可能都吐槽不完。

虽然我并不觉得会有人能从头看到这里,但是万一有的话,我祝你永远没有上面我的这种困扰,祝你幸福~

0X00 介绍

阅读并了解 LVM 需要了解:Linux 基本操作、分区概念、文件系统概念

首先 LVM 的全称是 Logical Volume Manager 逻辑卷管理。传统的方式是将一个磁盘分成类似于 sda1/sda2/sda3 的分区,然后再将这些分区格式化成类似于 ext4/xfs 这种文件系统,最后将文件系统挂载到某个目录上。但是这种方式下对磁盘空间进行重分配是比较麻烦的,将新安装的磁盘融入到现有系统中也是比较费力的,这就是 LVM 需要解决的问题。

总结下来 LVM 拥有这些功能

  1. LVM 可以方便的对现有逻辑卷进行压缩(初次分配多的空间不会浪费,可以压缩出来)
  2. 空闲的空间可以随时重新分配给逻辑卷(传统模式只能将空间分给最后一个分区,或者创建新分区)
  3. 新加入的磁盘也可以为其他逻辑卷扩容(传统模式并不方便为某个现有分区扩容)
  4. 可以将两块磁盘融合创建出一个更大的逻辑卷(两块 1T 磁盘可以创建出 2T 的分区)

特别需要注意的,RAID0 也可以将两个 1T 的磁盘合并为一个 2T 的,并且理论读写速度都会翻倍,但是这和 LVM 完全是两种不同的操作。

0X01 相关概念

开始使用 LVM 前需要先搞清楚它的几个基本概念

  • PV 是 Physical Volume 物理卷 — 从磁盘上分出来的物理分区
  • VG 是 Volume Group 卷组 — 多个 PV 组成的一个 Group
  • LV 是 Logical Volume 逻辑卷 — 从某个 VG 里创建出来的逻辑卷(可以格式化够挂载)
  • PE 是 Physical Extent 物理区域 — 是 PV 中最小的存储单元
  • LE 是 Logical Extent 逻辑区域 — 是 LV 中做小的存储单元

LVM Cropped

只是「简单用用」的话可以不管 PE/LE 这两个概念

阅读全文 »

0X00 前言

设计一个系统,不论是 Web 还是其他的什么形式,通过用户名和密码认证也是一个再正常不过的事情了。但是如何保存密码却是一个值得讨论的问题,相信各位最开始的一个有用户名和密码的程序多半也是用明文存储的密码吧 🤓

这里总结了六种比较常用于密码存储的方式,接下来可以逐一进行简单的分析以帮助我们更好的保护用户的密码

一清二白:明文存储密码,直接存 password

掩耳盗铃:使用 BASE64 之类的编码,存储为 cGFzc3dvcmQ=

盘古之法:使用早已不再安全的 md5 之类的摘要算法,存储为

5f4dcc3b5aa765d61d8327deb882cf99

祖宗之法:使用也已经不再安全的 sha-1 之类的摘要算法,存储为

5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8

凑合能用:使用现代的安全的例如 sha-256 之类额算法,存储为

5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8

现代手段:采用系统化的多次迭代的加盐哈希方式加密,例如常见的 PBKDF2

有兴趣的话可以把我上面的这几个 md5/sha-1/sha-256 拿来到 CrackStation 尝试解一下,就知道弱密码究竟有多危险了。

不过在开始之前要先进行一些简单的科普,以便于能够比较好的理解后面的东西。

名词解释

拖库:简单来说就是有不怀好意的小老弟获取了你数据库的访问权限,甚至将其 dump 然后下载下来了
撞库:当你有某个库的用户名和密码明文了,其实可以拿着用户名密码去其他系统也尝试登录,因为很多人的用户名和密码在各个系统都是一样的,比如同一个邮箱注册的密码也用的完全相同
碰撞:一般是说 hash 碰撞,在有一对原文和对应的 hash 值后再找到一个 hash 值相同但原文不同的的方法
:加盐是一种在进行散列前向原文指定位置插入内容,将散列前的原文变得很长从而使彩虹表等方式失效的行为

密码破解

常见的几种破解密码的方式有:暴力破解、用字典的暴力破解、彩虹表、社会工程学。

其中暴力破解最为暴力(废话噢),就是把所有可能的密码组合一个个的尝试一直尝试到天荒地老。如果是一个 8 位密码且只由大小写数字构成的话也有 62^8=218340105584896 这么多种组合,就算每秒钟能算出来十万个也需要七十年才能完全遍历一遍;
其次是用字典,字典就是将常用的弱密码、生日这种存起来,暴力破解的时候不再尝试所有组合,而是从字典中逐个取出来尝试,速度较快但是成功率降低了,毕竟只尝试了可能性最大的一小部分密码;
彩虹表也是类似于字典,但是字典每条只是一个密码,彩虹表是密码明文与 hash 之后的 key-value 对,当数据库被拖/泄露了之后,可以尝试拿泄露出来的 hash 值来反查密码原文;
社会工程学听起来好像很野,但是谁还没有过用生日和手机号作为密码解密的尝试呢 🤣

阅读全文 »

0X00 前言

本篇文章是这篇「使用 git stash save 将暂存区命名」的重置版。因为根据 Google 的统计数据我得知某些问题的关键词搜索出来之后我的博客排行会比较靠前,所以把最容易被各位点击到的文章做了个重置计划,改进之前的一些不足,争取能够说的更清楚一些,也能节省各位一点点时间,希望能真正的帮助到从搜索引擎点进来的各位~

0X01 极度精炼的使用说明

可以使用 git stash save "message" 的方式为 stash 起来的变动命名,方便后面再次使用。
git-stash-save

stash 起来过后可以使用 git stash list 来查看已经被 stash 的列表,这里可以看到已经有两条了,值得注意的是 stash 的 id 每次都在更新,最近 stash 的是 0,1 就是上次 stash 的,以此类推git-stash-list

如果需要从新应用某个 stash 的改动,可以使用 git stash apply STASH_ID 的方式,例如使用 git stash apply 1 就可以重新应用 id 为 1 的这个 stash。如果要丢弃掉某个 stash 的话使用 git stash drop STASH_ID 就可以了

0X00 换个方式定义函数

本篇内容不严格区分 function 与 method 🥹

我们都知道在 Python 中如何定义一个函数,只需要 def foo(arg_1, arg_2, *args, **kwargs)
就足够了。知道的稍微多一些呢可能知道「Python 中万物皆对象,所以函数的调用也只是调用了函数对象中的 __call__
方法」,所以我们可以尝试用这种方式调用一个函数

1
2
3
4
5
6
7
def say_hello():
print('hello, world')

say_hello.__call__()

# output
# hello, world

既然可以这样调用了,我们也就可以用类似的方法来定义一个假的
function,可以发现我们自定义了随便一个类,但是只要它实现了 __call__ 方法就可以被当做函数一样调用

1
2
3
4
5
6
7
8
class Foo:
def __call__(self):
print('hello, world')

foo = Foo()foo()

# output
# hello, world

0X01 callable

根据上面的方法可知我们可以用 hasattr(obj, '__call__')
来判断某个对象是不是函数,事实上我也确实在同事的代码里看到过这样用的。其实 Python 内置了一个名为 callable
的函数可以用,不过跟 hasattr(obj, '__call__') 并不完全一致

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
class Foo:
pass


class Bar:
def __call__(self):
pass

func = lambda x : x


print(hasattr(Foo, '__call__'), callable(Foo))
# output: (False, True)

print(hasattr(Foo(), '__call__'), callable(Foo()))
# output: (False, False)

print(hasattr(Bar, '__call__'), callable(Bar))
# output: (True, True)

print(hasattr(Bar(), '__call__'), callable(Bar()))
# output: (True, True)

print(hasattr(func, '__call__'), callable(func))
# output: (True, True)

测试代码的第一行 Foo 类因为没有实现 __call__ 方法所以 hasattr 返回的是
False,而它是一个类,调用它就会实例化一个对象出来,所以它是可调用的,所以 callable 就返回了 True;第二行
Foo 类也没有实现 __call__ 方法所以 hasattr 返回的是 False,而且它又只是个普通对象,不是一个 class
所以导致 callable 也返回了 False;第三行因为 Bar 类实现了 __call__ 方法所以 hasattrcallable
都返回了 True;第四行也同理;第五行本是一个函数,所以也都返回了 True

需要注意的是官方文档提到「callable 返回了 True 的不一定真的能调用成功,但是返回 False
的一定不能成功」,比如你强行给某个类设置了一个 __call__
但是又不是函数,可能就会出现这样的问题。不过你非要这么写的话,小心被同事打死噢 🤔

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Foo:
def __init__(self):
self.__call__ = '???'

foo = Foo()print(hasattr(foo, '__call__'))
print(callable(foo))
foo()

# output
# True
# True
# Traceback (most recent call last):
# File "hello.py", line 8, in <module>
# foo()
# TypeError: 'str' object is not callable

相关的官方文档:https://docs.python.org/3/library/functions.html#callable

0%