奶小牛

奶牛当爹了,值得庆贺的一件事儿。已经有大半个月在忙了,没有任何心思做自己的事儿了,不,孩子现在是最重要的事儿了。

月嫂

对于月嫂,我是不敢苟同没有好坏之分的,虽然大部分月嫂会把自己份内的事儿做好,但是也绝对是能省则省,她们会告诉你尿不湿比戒子好,但是对于稚嫩的婴儿,红屁股很大原因也是因为尿不湿吧,还有就是婴儿不能经常洗屁屁,试想一下,如果你屁股上糊着尿液或者便便,然后干了,你会是什么感觉?所以呢,月嫂很多时候是对的,但是也不是全对的,自己的孩子还是得自己上心才行。怎么说,尽信书则不如无书。

名字

这也是一个大事儿,家里人想了半个多月还是定不下来,每个人都是有自己的想法的,想一家人认同还真的很难,就像自己的孩子,我选的名字都被否了,最后还是闹得不开心。我觉得吧,孩子的名字就该父母自己取,俩人同意就够了,家人参考参考就可以了,要不定个名字比什么都难。

眼屎

孩子一只眼总是被眼屎糊住,老是睡一觉就睁不开。处理方法就是生理盐水擦拭眼屎,擦干净后滴上托百士眼药水,一日三到四次,每次一到两滴,前提是不是出生后就眼屎严重,而且眼睛没有明显红肿,否则还是建议去医院找医生看。

最近还有好多事儿要忙,感觉没孩子的时候真的该好好享受生活,有了孩子感觉日子都过得比以前快多了。希望孩子健康成长,无忧无虑。

amazon s3针对用户共用bucket的policy

amazon s3的官方有一篇介绍文章,但是少了一个”,”,导致并不能成功导入。

amazon有提供policy的在线生成工具,地址是http://awspolicygen.s3.amazonaws.com/policygen.html

amazon针对用户共用bucket,指定用户目录的policy在https://aws.amazon.com/blogs/security/writing-iam-policies-grant-access-to-user-specific-folders-in-an-amazon-s3-bucket/

具体policy可以使用下方的policy

{
  "Version":"2012-10-17",
  "Statement": [
    {
      "Sid": "AllowGroupToSeeBucketListInTheConsole",
      "Action": ["s3:ListAllMyBuckets", "s3:GetBucketLocation"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::*"]
    },
    {
      "Sid": "AllowRootAnd<shared-folder-name>ListingOfCompanyBucket",
      "Action": ["s3:ListBucket"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::<bucket-name>"],
      "Condition":{"StringEquals":{"s3:prefix":["","<shared-folder-name>/"],"s3:delimiter":["/"]}}
    },
    {
      "Sid": "AllowListingOfUserFolder",
      "Action": ["s3:ListBucket"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::<bucket-name>"],
      "Condition":{"StringLike":{"s3:prefix":
                  [
                       "<shared-folder-name>/${aws:username}/*",
                       "<shared-folder-name>/${aws:username}"
                  ]
               }
        }
    },
    {
       "Sid": "AllowAllS3ActionsInUserFolder",
       "Action":["s3:*"],
       "Effect":"Allow",
       "Resource": ["arn:aws:s3:::<bucket-name>/<shared-folder-name>/${aws:username}/*"]
    }
  ]
}

但是其实只保留最后两段是比较安全的,这样子无论是/根目录还是<shared-folder-name>共享目录都是不可以list的,只能list用户自己的名字命名的文件夹。

{
  "Version":"2012-10-17",
  "Statement": [
    {
      "Sid": "AllowListingOfUserFolder",
      "Action": ["s3:ListBucket"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::<bucket-name>"],
      "Condition":{"StringLike":{"s3:prefix":
                  [
                       "<shared-folder-name>/${aws:username}/*",
                       "<shared-folder-name>/${aws:username}"
                  ]
               }
        }
    },
    {
       "Sid": "AllowAllS3ActionsInUserFolder",
       "Action":["s3:*"],
       "Effect":"Allow",
       "Resource": ["arn:aws:s3:::<bucket-name>/<shared-folder-name>/${aws:username}/*"]
    }
  ]
}

这样子可以非常安全的隔离用户,也不用为每个用户建立一个bucket桶,还是很方便的。经过奶牛的测试,ACL最好就用默认的private,这样子安全性会更高。

三十岁后悔的二十件事

马上三十岁了,看到了狠多真诚的答案,在我有限的人生经验中,错过可以说直接上一个阶层的机会,至今后悔不已,往事并不如烟。

一、

相信命,我反而认为信命并不是极致的悲观、灰暗和迷信,而是理性又成熟深刻的价值观,知道山外有山,才能云淡风轻,这个世界本质的是不公平,每个人的起跑线是不一样,个体的差异不为人的意志所转移,最终的结果大不相同,是客观事实,明白这个现实我们才能更好的活自己。

三十岁之后的使命是接受自己是一个普通人。

二、

趁早买房,越早越好,那些告诉你生活还有诗和远方,通通都是错的,害人不浅,成熟的观念是一定要先买房,越早越好,相信我们国家。在买房这件事上的错误判断让我需要多付出很多年的代价。只要经济在发展,城市化进程还在走,也许买房可能是这辈子最正确的决定。

三、

越早理财越好,有人说没有几十万就不要理财,去享受生活,去看看世界,去旅游,这些观点通通都是错的,年轻的时候一定要存钱,在没有结婚之前,把收入分成几个账户:消费账户,应急账户,储蓄账户。把50%以上的收入存起来,少折腾股票或其他投资,股市那点本金基本收益率和货币基金差不多,没必要折腾,老实存起来,你的账户数字越来越多,你的自信就会越来越多,你的思维就会越来越广。

四、

自我预期管理,降低自我预期的阀值,没有人可以随便成功,降低预期能让自己好过不少,至少在你失败的时候能够舒服一点,小的时候认为自己是最牛逼的,自己能够改变世界,长大世界的现实是残酷的,没有什么鸡汤,奇迹是不会发生在你身上,学会接受失败和面对现实。

我一以前认识的大佬,做到上市公司的高管了,这几年自己创业,凡事亲力亲为,用电话陌拜谈业务,对方三秒钟就挂了,他把这个事情发在了朋友圈,很难想象原来这样的大佬也需要自己这么去干。多问问自己凭什么是你?

五、

恋爱要参照最优停止理论,也就是说,前37%的人如果都不合适,那么之后的每一个只要比前37%的要好,那么果断的去结婚,爱情是有情饮水饱,真正的婚姻是门当户对,家庭合伙制是婚姻的本质,一定要选性格好的,性格好的女人比有钱、漂亮之类优势更加明显。

六、

不要和老板做朋友,很多时候打工的思维在于拼命的把事情做对,而老板更多的是做对的事情,所以在层次和思维上是不可能成为朋友的,跟老板称兄道弟那就犯了大忌,表面越好,后面撕逼的结果就更严重。开始很美丽,结束的没道理。

七、

不要裸辞,一不爽就裸辞,会让自己的生活陷入一片慌乱,而后面的日子会越来越难过,辞职的前提一定是你学习不到任何东西了,没有任何成长,公司很垃圾,否则万不得已,必须要找到下一份工作再考虑辞职。

八、

少买知识付费的课程,市面上99%以上的课程本质上都是垃圾,对你没有任何好处,所有的方法论和成功方式都不适合你,基本连可应用的场景都没有,知识付费本质上是在贩卖焦虑,收智商税,省下的钱不如加入一些优质的社群,重复读几本经典的书并做总结来的划算。

九、

买保险,重要的事情要想三遍,保险不是骗子,保险是你人生变故后的最后一根救命稻草,是人生规划中必不可少的环节,如果你的经济实力不是特别的好,一定要买保险特别是重疾险,买消费型不买分红型,如果是家庭一定要给家庭中经济实力最强的人以及家庭的老人买好保险,人的一生中80%以上的概率都会得癌症。

十、

练习写作,好的文笔比好的数学重要多了,数学本质上来讲学到高中基本可以用来闯荡社会,你想想你这些年的数学丢到哪去了,数学老师的棺材板压不住了。

而写作是人生的必修课,而且每个人都需要写作,工作中你写的总结,计划,报告,邮件,微信等等都是写作,好的文笔能让你有更多的收入可能,说改变人生都不算夸张,见过很多原本普通的人,靠写作最后财富自由。

十一、

学习一项特长,你回头想想,你最牛逼的技能是什么?搜肠刮肚都想不到的时候,那么真的要趁早开始刻意练习了,在竞争领域,垂直擅长的领域,你的特长能够让你保持足够的竞争力和优势。

而且不觉得有特长的人特别的酷吗?

十二、

及时止损,很多事都需要成本代价,很多事没有任何的必要,及时止损的思维是为了不陷入损失黑洞陷阱,不一错再错,捡了西瓜丢了芝麻,错了就错了,失败了就是失败了,及时抽离。

十三、

明白人生而孤独,孤独的人并不可耻,每个人都是孤独的,享受孤独,人不能真正的去理解另外一个人,能明白自己的只有自己。

十四、

培养独立思考能力,在当下信息泛滥的时代,拥有独立思考的能力极其重要,做事之前多想想,事情真相是什么?为什么是这样?为什么不是这样?还有什么其他可能性吗?多种的思维方式去考虑问题,别让你的脑子成为别人的跑马场。

十五、

锻炼身体,好的身体绝对是本钱,高手的对决中,笑到最后的是看谁身体好,能够把对方熬败,好的身体是一种稀缺的资源,职场上更加如此,拼实力以外更多的是拼精力和体力,你想想再不锻炼能拼的过90后00后吗?你还能通宵吗?

十六、

尽量选择买贵的东西,为什么这么说,其实《断舍离》的本质,除了让我们明白人和物品的关系以外,更重要的是,物品是有能量的,如果你享受不了贵的物品,本质上是你内心觉得配不上这个物品,贵的东西能让你更加的自信,吸引力法则,你敢买宝马3以后一定买的起保时捷卡宴。其他东西同理。

十七、

学会演讲,无论在哪种场合我们需要演讲,开会发言,谈话,谈判,社交等都是演讲,生活中高频接触使用的技能一定要多训练。开不了口,害羞,害怕,会让自己人生丢分不少。

十八、

有条件就选择创业,其实是趁年轻多去折腾,多去试错才能知道自己究竟适合哪个方向,创业是改变限制条件,选择别人,而不是被人选择,做制定游戏规则的人。

当然,如果错了没关系,大不了还可以回头,到了四十岁,上有老下有小,车贷房贷,那真正是把人生困死,动不了,想都不敢想。

十九、

学会和自己相处,和自己内心的小宇宙相处,不执拗,不纠结,不自责,远离颠倒梦想,找到自己才能找到世界,千万不要和自己过不去。

二十、

自信,盲目的自信这也是自信,自信能让自己获得更多的资源和快感,自卑会让自己失去很多机会,自信让人进步,自卑让人退步。

本文作者:木木酱的小江湖 ,转载却未能找出原文出处。

WordPress的Google字体本地缓存方案

一直以来,Google字体都是困扰国内WordPress用户的一个问题。原因也很简单,载入慢,甚至可能由于载入慢导致页面卡死无法显示,这对于用户体验来说是很差的,disable google font这个插件也紧紧是对部分主题生效,对插件也没什么作用,而且测试下来效果很一般。如果你的主题还有禁止Google字体的选项那么就还挺好的,如果没有,奶牛建议可以试试Self-Hosted Google Fonts这个插件,效果很棒。

Self-Hosted Google Fonts的原理也很简单,首先就是扫描css文件里面的google fonts,然后把这些fonts下载到本地,之后把含有google fonts的css文件的链接替换掉,这样子下来,每次访问网站都是从本地读取Google字体,然后从本地分发至用户,虽然可能这样子会耗费很多流量在字体上,但是奶牛觉得还是挺值得的,至少网站的访问速度会提升很多,而且不用复杂地去修改css文件查找Google字体的链接然后本地话或者去除,而且也可以保存一个很好的字体显示效果。

最后附上链接:Self-Hosted Google Fonts

2018年总结

百度翻译总结是summary,我感觉用conclusion更贴切一些,今年感悟颇多。

刚才看电视剧《平凡的世界》,这是一部让我可以安静下来的电视剧,看过一遍,又在重看,拍的很好。

今年的思考很多,有过很多冲动,当然,我觉得有过更多的是想法,我不想再安于现状了。

人生到底该是个什么样子?我也不知道,现在,我只知时间金贵。有人说我很理想主义,确实是这样子,工作以来一直以为自己可以厚积薄发,但是发现厚积到是没做到,薄发就更不知道如何开始了。很无力,不知道该怎么开始,大概齐还是舍不得放下现在的安逸吧,但是说实话,现在的工作我真的是不想再做了,虽然我不知道我到底能不能成,能不能把自己的想法变成现实,但总归得试试看吧。在国企这种体制环境下,真的太难发育,跟自己的职业规划也相距颇远。

有时候想开个安逸的小店,就每天晒着太阳,有大把时间。

有时候就想写自己的程序,做自己看好的项目,一个人却很吃力。

最近喜欢上了一个字叫“芃”,感觉这才应该是一个人或者一个企业应有的态度。

关于亲情,友情,爱情以及2019年即将到来的baby,我心理上没做好太多准备,我可能一直都活在自己的世界里,很孤独。我希望每个人都是快乐的,每个人都可以一直笑。

我想做个有用的人,in other words,我想实现自己的人生价值,不想虚度人生,留下悔恨,已经错过了5年大好的人生,我还有多少5年可以浪费?

现在不止是有想法,也在回归,也在学习,只是慢一些,但希望结果不会让自己失望。我真心希望我可以有更多的时间去做自己喜欢的事儿,也有更多时间来陪伴我的家庭,我希望我可以有足够的精力来做这一切,我需要有精力,太需要了。这一年每天活得都很累,我想给自己放个假,思考下人生什么的。哪怕懒懒地睡上一个半月又能如何,只要能让自己振作起来又何尝不好。

2019年加油吧,奶牛。希望2018年的总结会让我在以后的日子里都如此充满动力。不悲观,做自己。

prism.js在ajax载入后失效问题解决方案

奶牛的小博客用了个ajax的主题,但是发现和prism.js有些小冲突,就是在ajax载入文章后,格式化的代码不能正常输出,其实解决方法也很简单,再次调用prism.js格式化一次即可。

Prism.highlightAll();

在ajax的回调函数里面重新highlight所有对象即可。

这个函数要放在ajax的回调函数里面,就是.done或者.success的回调函数里面,ajax升级的奶牛都快不认识了。

SSL证书的三个组成部分

今天签了几个证书,发现原来直接用crt文件的证书在部分手机上竟然显示证书不完整。仔细查了一下,原来ssl证书还有三个部分,一个是签发的crt,还有一个中间证书,还有一个根证书。但是对于桌面浏览器,只有crt证书部分就可以正常访问了,但是手机部分有时候会因为缺少中间证书和根证书导致证书不完整。

处理方法很简单:

cat ssl.ca-bundle >> ssl.crt

然后重启web服务器即可。

Linux下使用tar进行差异备份

说实话,奶牛这些年来一直都是手动完整备份文件,而且每次都是完整备份,其实很早之前就知道有增量备份这种东西了,可能是不太习惯吧,还是一直都是完整备份。今天就记录下tar进行差异备份和增量备份的一些心得。

首先说怎么做一个完整的备份

tar -czvf filename.tgz filename

这是普通的打包命令,没什么特别,下面我们使用一个-g参数

tar -g snapshot -czvf filename.tgz filename

执行完成后会生成一个snapshot文件,里面记录着备份信息。

这里插个分割线,说说增量备份和差异备份。

如果我们想进行增量备份,那么这个snapshot就需要一直更新,每次增量过后这个snapshot文件都会发生改变,如果我们需要还原,则需要把所有增量备份和完整备份一起还原。

如果我们想进行差异备份,那么我们需要把这个snapshot保护起来,然后每次都做针对完整备份的增量备份,那么恢复的时候我们只需要把最后一次增量备份和完整备份一起还原。

优缺点:增量备份占用的空间要小于差异备份,但是恢复起来非常麻烦,特别是比如一个月内只做一次完整备份,其它每天只做增量备份,那么恢复的时候要恢复很多个增量备份文件。

差异备份占用空间要比增量备份大一些,但是如果备份文件修改较少,则差异备份的文件也不会很大,恢复的时候只需要恢复完整备份和差异备份即可,工作量会小很多。

好了,回归正题,我们这里就讲差异备份,增量备份网上一堆参考,不多介绍了。

cp snapshot snapshot.backup
tar -g snapshot -czvf filename-1.tgz filename
mv snapshot snapshot-1.backup
cp snapshot.backup snapshot

这样一来,我们就在snapshot-1.backup中记录了这次差异备份的变化信息了,然后差异备份文件是filename-1.tgz

如果我们要备份的文件或目录里面存在软链接,而我们又需要备份其中软链接对应的文件或目录的源文件,我们则需要增加一个-h属性

tar -czvhf filename.tgz filename

查看tgz文件内容

tar -tvf filename.tgz

好了,奶牛今天的记录至此。

Comodo Positive SSL申请过程

黑五过去了,留下了一些折腾。不过还好,今天蛮有收获的。

说下Comodo Positive SSL到底怎么申请怎么用。对于Nginx用户来说,添加SSL就需要两个文件,一个是private.key,一个是domain.cer。其中private.key是我们自己生成的,cer是得花钱买的,当然也可以自己签,但是自己签的浏览器不认。

private.key的生成我们需要了解一个东西叫CSR。根据百科的内容是这样介绍的:

CSR是Certificate Signing Request的英文缩写,即证书请求文件,也就是证书申请者在申请数字证书时由CSP(加密服务提供者)在生成私钥的同时也生成证书请求文件,证书申请者只要把CSR文件提交给证书颁发机构后,证书颁发机构使用其根证书私钥签名就生成了证书公钥文件,也就是颁发给用户的证书。

生成private.key的方法很多,奶牛就不介绍了,使用linux或者windows下的签名软件生成,或者现在已经有很多网站支持在线生成CSR了,直接生成就可以。生成完成后我们得到csr.cer和private.key两个文件。

然后我们需要将csr.cer的内容提交给Comodo,然后需要一个验证过程,叫Domain Control Validation (DCV) 。这个验证过程有几种方式:

1.邮件,但是需要域名的[email protected]的邮箱可以接收邮件,这个比较麻烦,pass掉。

2.dns,这个可以,添加一个记录即可。

3.http文件,这个需要你下载他们的验证文件,然后使http://domain.com/.well-known/pki-validation/file.txt可以验证这个文件,这个方案也可以。

验证通过后就可以得到domain.cer了,然后修改nginx的conf文件增加ssl证书即可。

配置Django的Celery异步之路踩坑

终于的终于,奶牛还是踏上了新的踩坑之路。

人生苦短,我用python。

看到这句话的时候,感觉可能确实是很深得人心,不过每每想学学,就又止步,年纪大了,感觉学什么东西都很慢,很难,精神啊注意力啊思维啊都跟不上。今天奶牛来分享自己今天踩的一个坑。

先说说配置过程吧,初学Django,啥都不懂,当然,python也很水,啥东西都得现查现用。Django安装还是很简单的。

apt-get install python3
pip3 install django

嗯,就是两条命令的事儿。

再说celery的安装:

pip3 install celery
pip3 install redis==2.10.6

目前奶牛所在的时间redis for python的版本是redis-3.0.1,为什么要用2.10.6呢?因为3.0.1压根配置就无法运行!!!

继续安装redis server

apt-get install redis
service redis start

然后就可以按照celery的官方教程走了,放个URL:http://docs.celeryproject.org/en/latest/django/index.html

python3 manage.py startproject nenew
cd nenew
python3 manage.py startapp nenewapp
touch ./nenew/celery.py
touch ./nenewapp/tasks.py

然后增加nenew/nenew/celery.py内容为

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'nenew.settings')

app = Celery('nenew')

# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
#   should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')

# Load task modules from all registered Django app configs.
app.autodiscover_tasks()


@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

增加nenew/nenew/__init__.py的内容

from __future__ import absolute_import, unicode_literals

# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app

__all__ = ('celery_app',)

增加nenew/nenewtest/tasks.py的内容

# Create your tasks here
from __future__ import absolute_import, unicode_literals
from celery import shared_task


@shared_task
def add(x, y):
    return x + y


@shared_task
def mul(x, y):
    return x * y


@shared_task
def xsum(numbers):
    return sum(numbers)

在nenew/nenew/settings.py中增加和修改

...

ALLOWED_HOSTS = ['*']
....

INSTALLED_APPS = [
...
    'nenewtest',
]

...

CELERY_BROKER_URL = 'redis://localhost:6379/1'
CELERY_RESULT_BACKEND = ‘redis://localhost:6379/0'

在nenew/nenewtest/views.py中增加或修改为

from django.shortcuts import render
from django.http import HttpResponse
from .tasks import add
# Create your views here.
def nenewtest(request):
    result = add.delay('2','2')
    result.ready()
    return HttpResponse('nenew Django Celery worker run !')

最后把views添加到nenew/nenew/urls.py中

from django.contrib import admin
from django.urls import path
from nenewtest import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('test/', views.nenewtest),
]

然后在项目目录nenew执行

celery -A nenew worker -l info

这时候worker启动正常会显示:

-------------- [email protected] v4.2.1 (windowlicker)
---- **** -----
--- * ***  * -- Linux-4.15.0-39-generic-x86_64-with-Ubuntu-18.04-bionic 2018-11-23 17:31:25
-- * - **** ---
- ** ---------- [config]
- ** ---------- .> app:         nenew:0x7fdc5a155cc0
- ** ---------- .> transport:   redis://localhost:6379/1
- ** ---------- .> results:     redis://localhost:6379/0
- *** --- * --- .> concurrency: 1 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** -----
 -------------- [queues]
                .> celery           exchange=celery(direct) key=celery

这样类似的信息,然后我们启动项目,这里需要新开一个shell:

python3 manage.py runserver 0:80

这样我们就可以通过80端口直接访问我们的web了。地址是http://locahost/test

当我们这里访问正常后,在worker界面会有

[2018-11-23 18:09:19,469: INFO/MainProcess] Received task: nenewtest.tasks.add[35faa0fe-dd48-4f8d-9559-516556a93a40]
[2018-11-23 18:09:19,470: INFO/ForkPoolWorker-1] Task nenewtest.tasks.add[35faa0fe-dd48-4f8d-9559-516556a93a40] succeeded in 0.00031037399821798317s: '22'

如下语句表示执行成功,这样子就表示通过Django的网页我们对celery任务的异步执行成功。

当然,按照我的方法是可以一步成功的,因为奶牛已经踩了一整天的坑了,被一个错误郁闷得不要不要的。

AttributeError: 'float' object has no attribute 'items'

就是这个错误,查遍国内的所有网站都没有结果,然后就去bing的国际版查,然后发现果然是有bug在啊,奶牛这一天浪费得可真是够了。

这是celery的一个issue,在地址https://github.com/celery/celery/issues/5175 ,issue里面提及在2018/11/22日 it’s fixed in kombu and celery master。问题的根源是celery对redis3的支持不好,补救方法是

Solution: Roll back redis with pip: pip install redis==2.10.6

然后在commit里面找到是对requirements/extras/redis.txt文件进行版本限定。

-redis>=2.10.5
+redis>=2.10.5,<3

好了,踩坑总算结束了。毕竟是新手,很多问题可能就是潜意识认为是自己的代码有问题,实际。。。实际可能并不是这样子,得多关注源码的更迭和问题处理才好。