docker容器不能启动的解决方法

因为系统异常退出, 导致容器不能启动, 提示下面错误:

  1. root@host:~# docker start gogs
  2. Error response from daemon: OCI runtime create failed: container with id exists: 1d8cac1e6ed19db70171786f102f66194d0b2fc5c9f8e6b58da73ae21b319dc8: unknown
  3. Error: failed to start containers: gogs

解决方法和步骤:

  1. 进入系统目录 cd /var/run/docker/runtime-runc/moby/
  2. 删除对应的id目录, 比如这里是 rm -rf 1d8cac1e6ed19db70171786f102f66194d0b2fc5c9f8e6b58da73ae21b319dc8

之后就可以成功 docker start gogs 了.

windows 10 无法连接samba的解决方法

1、首先按window+R键打开运行键入regedit 启动本地组策略编辑器。
2、进入地址计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\ParametersAllowInsecureGuestAuth设置为1
3、进入计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\LanmanWorkstation,将AllowInsecureGuestAuth设置为1

为什么程序员反对乱改需求

综合整理:程序员的那些事

为什么程序员/设计师怕改需求?网上有类似的段子,比如:「杀一个程序员不需要用枪,改三次需求就可以了。」

有网友在知乎上提问「如何向外行解释产品经理频繁更改需求为什么会令程序员烦恼?」。

某网友的回复:

你去饭店,坐下来。
“服务员,给我来份宫保鸡丁!”
“好嘞!”
——————这叫原始需求

大厨做到一半。
“服务员,菜里不要放肉。”
“不放肉怎么做啊?”
“不放肉就行了,其它按正常程序做,不就行了,难吗?”
“好的您稍等”
——————中途需求变更

厨房:
大厨:“你大爷,我肉都回锅了”
服务员:“顾客非要要求的嘛,你把肉挑出来不就行了吗”
大厨:“行你大爷”
然而还是一点点挑出来了
——————改动太大,部分重构

餐厅:
“服务员,菜里能给我加点腐竹吗?”
“行,这个应该简单。”
——————低估改动成本

厨房:
大厨:“你TMD,不知道腐竹得提前泡水?炒到一半才说?跟他说,想吃腐竹就多等半天”
服务员:“啊你怎么不早说?”
大厨:“早说你MLGB我怎么知道他要往宫保鸡丁里放腐竹”
然而还是去泡腐竹了
——————新需求引入了新研发成本

餐厅:
“服务员,还是把肉加回去吧”
“您不是刚说不要肉吗”
“现在又想要了”
“…好的您稍等”
——————某一功能点摇摆不定

厨房:
大厨:“日你啊,菜都炒过火了你让我放肉?还好肉我没扔”
服务员:“客户提的要求你日我干嘛?”
大厨:“你就不能拒绝他啊?啊?”
服务员:“人家是客户嘛。”
——————甲方是大爷

餐厅:
“服务员!服务员!”
“来了来了,你好?”
“怎么这么半天啊?”
“稍等我给您催催啊”
——————改动开始导致工期延误

厨房:
大厨:“催你M催,腐竹没泡好,我还得重新放油,他要想吃老的也行,没法保质保量”
——————开发者请求重新排期

餐厅:
服务员:“抱歉,加腐竹的话得多等半天,您别着急哈”
“我靠要等那么久?我现在就要吃,你们能快点吗?”
“行…您稍等”
——————甲方催活

厨房:
大厨:“我日他仙人板板,中途改需求又想按期交付,逗我玩呢?”
服务员:“那我问问,要不让他们换个菜?”
大厨:“再换我就死了”
——————开发者开始和中间人pk

餐厅:
“服务员,这样吧,腐竹不要了,换成蒜毫能快点吗?对了,顺便加点番茄酱”
——————因工期过长再次改动需求

厨房:
大厨:“我日了狗啊,你TM不知道蒜毫也得焯水啊?还有你让我怎么往热菜里放番茄酱啊??”
服务员:“焯水也比等腐竹强吧,番茄酱往里一倒不就行了吗?很难吗?”
大厨:“草。腐竹我还得接着泡,万一这孙子一会又想要了呢。”
——————频繁改动开始导致大量冗余

餐厅:
“服务员,菜里加茄丁了没有?我去其它饭店吃可都是有茄丁的”
“好好好您稍等您稍等”
——————奇葩需求

厨房:
大厨:“我去他二大爷他吃的是斯里兰卡三流技校炒的宫保鸡丁吗?宫保鸡丁里放茄丁??”
服务员:“茄丁抄好了扔里边不就行了吗?”
大厨:“那TM还能叫菜吗?哪个系的?”
服务员:“客户要,你就给炒了吧。”
大厨:“MB你顺道问问他腐竹还要不要,我这盆腐竹还占着地方呢不要我就扔了”
——————奇葩你也得做

餐厅:
“服务员,还要多久能好啊”
“很快,很快…”
“再给我来杯西瓜汁。”
“…好”
“我再等10分钟,还不好我就走了,反正还没给钱。”
“很快,很快…”
——————黑暗前的最后黎明

10分钟后
“咦,我上次吃的不是这个味啊?”
从厨房杀出来的大厨:“我TM就日了你的狗…”
——————最终决战

——————
你=客户
服务员=客户经理+产品经理
大厨=码农
请自行转换…
——————
注:以上场景已极度夸张,实际生产生活中码农和PM是和睦友好的相亲相爱的一家人
——————
注:对于做2C产品的公司,你=公司大boss

mpvue小程序开发 渲染层网络层错误 问题的解决方法

直接上解决方法:

servicewechat.com 加入防盗链白名单问题解决

问题发现和排查过程

用mpvue开发小程序的时候, 遇到了渲染层网络层错误, 公司静态资源配置了防盗链功能, 使用location.href看到的也是 127.0.0.1 的本地地址, 本以为把127.0.0.1加入防盗链的白名单就可以了, 结果还是报这个错误, 比较扯淡的是这个控制台还看不到真正的图片请求, 最后用 fiddler 抓了一下包, 才发现refresh居然是 https://servicewechat.com/wx7d3c7a42f044667b/devtools/page-frame.html, 最后把 servicewechat.com 加入防盗链白名单问题解决.

调试工具报错信息:

fiddler请求头信息:

小程序客服消息处理

三种消息类型:

  1. // 文本消息
  2. {
  3. "signature": "ee6e400de7972484ec6f3014c2f77504925a4707",
  4. "timestamp": "1552298008",
  5. "nonce": "540004383",
  6. "openid": "oPzrj5EAP25lzOVW6qa0m8MUlLXA",
  7. "encrypt_type": "aes",
  8. "msg_signature": "74c419155e49cefab8ab1dbd440b9389acc47e2a",
  9. "URL": "http:\/\/qiang.lt.ngapp.net\/wechat\/noti/fy",
  10. "ToUserName": "zhaishuaigan",
  11. "FromUserName": "oPzrj5EAP25lzOVW6qa0m8MUlLXA",
  12. "CreateTime": 1552293166,
  13. "MsgType": "text",
  14. "Content": "hello",
  15. "MsgId": 1,
  16. "Encrypt": "PloOW0ucj9SkMpMC...."
  17. }
  18. // 事件消息
  19. {
  20. "signature": "3e5860da822266b9f03f8d5380615f9be0ae2db7",
  21. "timestamp": "1552301914",
  22. "nonce": "693467019",
  23. "openid": "oPzrj5EAP25lzOVW6qa0m8MUlLXA",
  24. "encrypt_type": "aes",
  25. "msg_signature": "eda0cdd567b35df4501ee2041e0d191db81798f2",
  26. "ToUserName": "gh_cc23a0a84984",
  27. "FromUserName": "oPzrj5EAP25lzOVW6qa0m8MUlLXA",
  28. "CreateTime": 1552301914,
  29. "MsgType": "event",
  30. "Event": "user_enter_tempsession",
  31. "SessionFrom": "open-type='contact'",
  32. "Encrypt": "oMP\/xo2RdcbK07vvoxxxx....."
  33. }
  34. // 图片消息
  35. {
  36. "signature": "ebd79f0c44f01dc26ef83ffeeadbdb3af5b960da",
  37. "timestamp": "1552302190",
  38. "nonce": "1322948029",
  39. "openid": "oPzrj5EAP25lzOVW6qa0m8MUlLXA",
  40. "encrypt_type": "aes",
  41. "msg_signature": "06613ca44e189d95140166898f80a27ab10baa80",
  42. "ToUserName": "gh_cc23a0a84984",
  43. "FromUserName": "oPzrj5EAP25lzOVW6qa0m8MUlLXA",
  44. "CreateTime": 1552302190,
  45. "MsgType": "image",
  46. "PicUrl": "http:\/\/mmbiz.qpic.cn\/mmbiz_jpg\/WwPGxFUiaTRZ6zVvTTGVbhfa9Vic801ux7OHobAAiaD3xRMYeJzbic4ISvwn736dpK0OMTlaYvX7GoTRgE8LqObkIQ\/0",
  47. "MsgId": 22223624286040849,
  48. "MediaId": "3WiHLigPtkJtqoLvPD2HgPsAtb3vzDvTWyo0sP5s-dshtS7oZOlCW7c3RuD1nwBt",
  49. "Encrypt": "gictSCCy+Zxxxx...."
  50. }

ThinkPHP 5.1保存消息代码

  1. $request = request()->param();
  2. $data = [
  3. 'signature' => $request['signature'],
  4. 'timestamp' => $request['timestamp'],
  5. 'nonce' => $request['nonce'],
  6. 'openid' => $request['openid'],
  7. 'encrypt_type' => $request['encrypt_type'],
  8. 'msg_signature' => $request['msg_signature'],
  9. 'to_username' => $request['ToUserName'],
  10. 'from_username' => $request['FromUserName'],
  11. 'msg_type' => $request['MsgType'],
  12. 'msg_id' => isset($request['MsgId']) ? $request['MsgId'] : '',
  13. 'encrypt' => isset($request['Encrypt']) ? $request['Encrypt'] : '',
  14. ];
  15. $msgInfo = [];
  16. switch ($request['MsgType']) {
  17. case 'text':
  18. $msgInfo['text'] = $request['Content'];
  19. break;
  20. case 'image':
  21. $msgInfo['pic'] = $request['PicUrl'];
  22. $msgInfo['media_id'] = $request['MediaId'];
  23. break;
  24. case 'event':
  25. $msgInfo['event'] = $request['Event'];
  26. $msgInfo['session_from'] = $request['SessionFrom'];
  27. break;
  28. }
  29. $data['msg_info'] = json_encode($msgInfo);
  30. CustomerMessage::create($data);
  31. return '';

数据库表结构设计

  1. <?php
  2. use think\migration\Migrator;
  3. use think\migration\db\Column;
  4. class CreateCustomerMessageTable extends Migrator
  5. {
  6. public function change()
  7. {
  8. $this->table('customer_message')
  9. ->addColumn(Column::string('signature')
  10. ->setDefault('')
  11. ->setComment('签名'))
  12. ->addColumn(Column::integer('timestamp')
  13. ->setDefault(0)
  14. ->setComment('时间戳'))
  15. ->addColumn(Column::string('nonce')
  16. ->setDefault('')
  17. ->setComment('随机数'))
  18. ->addColumn(Column::string('openid')
  19. ->setDefault('')
  20. ->setComment('客户id'))
  21. ->addColumn(Column::string('encrypt_type')
  22. ->setDefault('')
  23. ->setComment('加密方式'))
  24. ->addColumn(Column::string('msg_signature')
  25. ->setDefault('')
  26. ->setComment('消息签名'))
  27. ->addColumn(Column::string('to_username')
  28. ->setDefault('')
  29. ->setComment('消息接收者'))
  30. ->addColumn(Column::string('from_username')
  31. ->setDefault('')
  32. ->setComment('消息来源'))
  33. ->addColumn(Column::string('msg_type')
  34. ->setDefault('')
  35. ->setComment('消息类型'))
  36. ->addColumn(Column::text('msg_info')
  37. ->setNull(true)
  38. ->setComment('消息内容'))
  39. ->addColumn(Column::string('msg_id')
  40. ->setDefault('')
  41. ->setComment('消息id'))
  42. ->addColumn(Column::text('encrypt')
  43. ->setNull(true)
  44. ->setComment('加密数据'))
  45. ->addColumn(Column::dateTime('create_time')
  46. ->setDefault('CURRENT_TIMESTAMP')
  47. ->setComment('创建时间'))
  48. ->addColumn(Column::dateTime('update_time')
  49. ->setDefault('CURRENT_TIMESTAMP')
  50. ->setComment('更新时间'))
  51. ->addColumn(Column::dateTime('delete_time')
  52. ->setNull(true)
  53. ->setComment('删除时间'))
  54. ->create();
  55. }
  56. }

收藏一些docker镜像和使用方法

  1. version: '2'
  2. services:
  3. proxy:
  4. image: 'jwilder/nginx-proxy'
  5. volumes:
  6. - /var/run/docker.sock:/tmp/docker.sock
  7. ports:
  8. - '80:80'
  9. mysql:
  10. image: mysql:5.7
  11. environment:
  12. - MYSQL_ROOT_PASSWORD=root
  13. volumes:
  14. - "./data/mysql:/var/lib/mysql"
  15. ports:
  16. - '3306:3306'
  17. redis:
  18. image: redis
  19. def:
  20. image: zhaishuaigan/php
  21. volumes:
  22. - "./:/app"
  23. links:
  24. - mysql
  25. - redis
  26. environment:
  27. - VIRTUAL_HOST=shuai.cn
  1. docker run -p 80:80 -p 443:443 -itd --restart always -v /var/run/docker.sock:/tmp/docker.sock:ro --name proxy neilpang/nginx-proxy
  2. docker run -d --name api --restart=always -v /www/api:/app -e VIRTUAL_HOST=api.ngapp.net -e ENABLE_ACME=true zhaishuaigan/php:tp5
  3. docker run -d --name api --restart=always -v /root/www/api:/app -e VIRTUAL_HOST=api.admin-ui.cn -e ENABLE_ACME=true zhaishuaigan/php

php storm安装后要做的事

1. 破解

地址: http://idea.lanyus.com/

写给刚入行的程序员

源地址: 顶级程序员

1.作为前端开发者,使用双显示器能大幅提高开发效率。

2.学编程最好的语言不是PHP,是English。

3.自己做的东西交付之前先测试一遍。

4.问别人之前最好先自己百度,google一下,以免问出太低级的问题。

5.把觉得不靠谱的需求放到最后做,很可能到时候需求就变了,或者取消了。

6.读好书,垃圾书会浪费你时间。

7.不要炫技,面向人脑编程更便于维护。

8.没事别重复造轮子,你造的轮子大多数时候只有你觉得好用。接手你的轮子的人会在背后骂你上百遍。

9.不要先写框架再写实现。最好反过来,从原型中提炼框架。

10.新技术一定不要找书,书一旦印出来就过时了。

11.请勿久坐,多喝水,尤其是遇到很久都解决不了的问题的时候,多走动走动。

12.考虑可维护性比考虑性能更重要。

13.越难解决的bug往往犯的错误越低级。

14.比起鼓励师,不如给程序员找一个靠谱的产品经理。

15.熬夜低效率写代码,不如好好睡觉。

16.你遇到的问题,大多数人都遇到过,并且网上都有完整的解决方案,你找不到,只是你懒得去找。

17.多沟通,不少加班工作是由于沟通少造成的。

18.普通程序员+google=超级程序员。实在不行,百度也可以,学会利用搜索引擎来辅助自己解决问题。

19.早点找女朋友,生活作息会更健康。你懂的!

20.永远别小看程序媛。即使是青铜,说不定背后有个王者在帮她。

PHP开发清单

最近读了<<清单革命>>后, 感觉清单很适合程序员使用, 可以避免一些低级错误, 有效降低线上bug发生的概率.

本地开发清单

  • 需求分析
  • 数据库字段设计
  • 构建代码框架
  • 上线差异化配置说明
  • 具体逻辑实现
  • 本地新功能测试
  • 测试关键模块是否正常
  • 边界值测试
  • 注入测试
  • 查看 sql 日志
  • 查看 错误 日志
  • 提交代码

上线清单

  • 列出新版本更新功能
  • 确认所有开发人员代码是否提交
  • 更新本地代码
  • 清除本地所有日志
  • 测试本地所有新功能是否正常
  • 测试关键模块是否正常
  • 边界值测试
  • 注入测试
  • 查看 sql 日志
  • 查看 错误 日志
  • 上线部署

nodejs开发的神器 now

now是什么?

now 允许您轻松、快速和可靠地将JavaScript(Node.js)或Docker支持的网站、应用程序和服务带到云中。实际上,包含package.json或Dockerfile的任何目录都可以通过一个命令:now传输到云。

每次部署一个项目,now 将提供一个新的、唯一的URL(甚至在上传完成之前)。这些URL将看起来像这样(我的应用程序-随机字符串):my-app-erkgfjtrna.now.sh 。

当您部署到生产时,您只需选择适当的别名(自定义域)即可。

官网地址: https:/zeit.co

使用方法

  1. 下载命令行工具: npm install -g now
  2. 创建开发目录 mkdir my-project && cd my-project
  3. 创建package.json
    1. {
    2. "name": "koa",
    3. "version": "1.0.0",
    4. "description": "",
    5. "main": "index.js",
    6. "scripts": {
    7. "start": "node index.js"
    8. },
    9. "author": "",
    10. "license": "ISC",
    11. "dependencies": {
    12. "koa": "^2.6.1"
    13. }
    14. }
  4. 创建index.js
    1. const Koa = require('koa');
    2. const app = new Koa();
    3. app.use(ctx => {
    4. ctx.body = 'Hello Koa';
    5. });
    6. app.listen(80);
  5. 登录 now login 然后输入邮箱地址收取验证邮件, 点击邮件里的验证链接, 这里需要翻墙, 因为验证页面有个js在google上.
  6. 执行 now --public 会输出类似下面的结果.
    1. > Deploying D:\xxxx\my-project under shuai
    2. > Synced 2 files (366B) [1s]
    3. > Using Node.js 8.11.3 (default)
    4. > https://my-project-lcjucjkwmi.now.sh [in clipboard] (sfo1) [3s]
    5. > Building
  7. 执行完成后, 就可以打开上面的地址看到运行结果

别名使用

now --public && now alias shuai
即可生成一个 shuai.now.sh 的地址, 方便记忆

使用自己的域名

now --public && now alias shuai.com
需要根据提示验证域名所有权就能使用自己的域名访问了, 而且自动生成https证书