menu Chancel's Blog
rss_feed lightbulb_outline

我的笔记

Nounplus/Grammar Check Online.. - 英文语法检查工具

Smart Grammar Checker Online Tool free - nounplus

  • 一款在线web检查英文语法工具

gingersoftware

  • 支持多个平台的英文语法检查工具

Grammarly Spell Checker - Chrome插件

  • Chrome扩展插件检查英文语法

以上均为工具,仅适用于英文不太好的水平

Web Site Star 2019-10-17 16:10:53 location_on

Git - Bash脚本判断本地仓库代码是否需要更新

线上的一些小项目偶尔需要实现自动更新,那么可以考虑结合Git仓库的Master来做自动更新,小的项目没必要考虑去写一个Jenkins配置单

首先要配置项目无需验证账户密码就可以拉取文件,执行完下面命令,输入账户密码后下次拉取代码不会重新询问账户密码

git config --global credential.helper store
git pull

设置一下自动拉取Master分支,然后结合Supervisor重启一次应用程序即可啦

#!/bin/bash
# author: Chancel.Yang

projectPath='/home/Apps/hello-world'
projectName='hello-world'
cd $projectPath
git fetch
UPSTREAM=${1:-'@{u}'}
LOCAL=$(git rev-parse @{0})
REMOTE=$(git rev-parse "$UPSTREAM")
BASE=$(git merge-base @{0} "$UPSTREAM")
if [ $LOCAL = $REMOTE ]; then
    echo "Up-to-date"
elif [ $LOCAL = $BASE ]; then
    supervisorctl stop $projectName
    # 脚本由Root执行,但拉取不可用Root用户否则项目执行用户Apps无权限执行项目
    su - Apps git pull
    supervisorctl start $projectName

执行这个脚本就可以获取到Github远程仓库与本地仓库的版本差别

注意git的旧版本不允许使用@,所以你可能需要使用@ {0}

Develop Base Git 2021-01-11 04:37:41 location_on

Vim - 忘记sudo之后如何保存需要root权限的文件?

在Linux下编辑文件保存时经常会遇到

"readonly-file-name" E212: Can't open file for writing

这个时候就很尴尬了,尤其是修改很大的文件,无法保存是一件头疼的事情,一般这种情况下你只好先另存文件再重新打开编辑文件,对于只是忘了敲sudo命令来说这样的操作太过于繁琐了

其实Vim是支持在编辑状态下直接获取Root权限而无需退出Vim的,只需要在Vim里执行这行命令即可

:w !sudo tee %

Operating System Linux 2019-10-16 17:49:16 location_on

Git Stash - 不提交代码保存当前代码的修改并切换分支进行其他工作

Git 工具 - 储藏(Stashing)

经常有这样的事情发生,当你正在进行项目中某一部分的工作,里面的东西处于一个比较杂乱的状态,而你想转到其他分支上进行一些工作。问题是,你不想提交进行了一半的工作,否则以后你无法回到这个工作点。解决这个问题的办法就是git stash命令。

重点

  • git stash: 备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致。同时,将当前的工作区内容保存到Git栈中
  • git stash pop: 从Git栈中读取最近一次保存的内容,恢复工作区的相关内容。由于可能存在多个Stash的内容,所以用栈来管理,pop会从最近的一个stash中读取内容并恢复
  • git stash list: 显示Git栈内的所有备份,可以利用这个列表来决定从那个地方恢复
  • git stash clear: 清空Git栈

例子

# chancel @ chancel-cp in /tmp/stash on git:master o [12:04:03] 
$ git status
On branch master
nothing to commit, working tree clean

# chancel @ chancel-cp in /tmp/stash on git:master o [12:05:11] C:130
$ echo "I'm fine,fuck you" > hello.py

# chancel @ chancel-cp in /tmp/stash on git:master x [12:05:17] 
$ ll
total 8.0K
-rw-r--r-- 1 chancel chancel  4  9月  6 12:03 123.txt
-rw-r--r-- 1 chancel chancel 18  9月  6 12:05 hello.py

# chancel @ chancel-cp in /tmp/stash on git:master x [12:05:18] 
$ git add .

# chancel @ chancel-cp in /tmp/stash on git:master x [12:05:21] 
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   hello.py


# chancel @ chancel-cp in /tmp/stash on git:master x [12:05:24] 
$ git stash
Saved working directory and index state WIP on master: a404cee first commit

# chancel @ chancel-cp in /tmp/stash on git:master o [12:05:37] 
$ git status
On branch master
nothing to commit, working tree clean

# chancel @ chancel-cp in /tmp/stash on git:master o [12:05:41] 
$ ll     
total 4.0K
-rw-r--r-- 1 chancel chancel 4  9月  6 12:03 123.txt

# chancel @ chancel-cp in /tmp/stash on git:master o [12:05:54] 
$ echo "hello" > hello.txt

# chancel @ chancel-cp in /tmp/stash on git:master x [12:06:17] 
$ ll 
total 8.0K
-rw-r--r-- 1 chancel chancel 4  9月  6 12:03 123.txt
-rw-r--r-- 1 chancel chancel 6  9月  6 12:06 hello.txt

# chancel @ chancel-cp in /tmp/stash on git:master x [12:06:21] 
$ git add hello.txt 

# chancel @ chancel-cp in /tmp/stash on git:master x [12:06:26] 
$ git stash
Saved working directory and index state WIP on master: a404cee first commit

# chancel @ chancel-cp in /tmp/stash on git:master x [12:07:20] 
$ ll
total 8.0K
-rw-r--r-- 1 chancel chancel 4  9月  6 12:03 123.txt
-rw-r--r-- 1 chancel chancel 6  9月  6 12:07 hello.txt


# chancel @ chancel-cp in /tmp/stash on git:master x [12:07:45] 
$ git stash pop
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   hello.txt

Dropped refs/stash@{0} (b9963709ffa5959d2341b31378d9b3457a2b9798)

# chancel @ chancel-cp in /tmp/stash on git:master x [12:07:56] 
$ ll
total 8.0K
-rw-r--r-- 1 chancel chancel 4  9月  6 12:03 123.txt
-rw-r--r-- 1 chancel chancel 6  9月  6 12:07 hello.txt

# chancel @ chancel-cp in /tmp/stash on git:master x [12:07:58] 
$ git stash pop
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   hello.py
    new file:   hello.txt

Dropped refs/stash@{0} (172bdcff963c2786becbb9acd526d968b279b3e0)

# chancel @ chancel-cp in /tmp/stash on git:master x [12:08:02] 
$ ll
total 12K
-rw-r--r-- 1 chancel chancel  4  9月  6 12:03 123.txt
-rw-r--r-- 1 chancel chancel 18  9月  6 12:08 hello.py
-rw-r--r-- 1 chancel chancel  6  9月  6 12:07 hello.txt

Develop Base Git 2019-10-16 17:48:46 location_on

“crontab -e” 的使用

crontab -e 与 修改/etc/crontab文件的格式是有差异的

# /etc/crontab文件 定时每天早上5点使用root用户执行脚本
0  5  *  *  * root bash /opt/script/xswl.sh

# crontab -e指令直接进入vi编辑模式,不再需要填写用户,因为这是当前用户的定时任务
0 5 * * * bash /opt/script/xswl.sh

添加之后两者均要检查

  • crond服务是否已经运行
  • 脚本"xswl.sh"是否有执行权限

Operating System Linux 2019-10-16 17:46:07 location_on

Python Flask 执行异步操作

根据官方文档 - concurrent.futures,Python支持的异步操作代码如下

import time
from concurrent.futures import ThreadPoolExecutor
def wait_on_b():
    time.sleep(5)
    print(b.result())  # b will never complete because it is waiting on a.
    return 5

def wait_on_a():
    time.sleep(5)
    print(a.result())  # a will never complete because it is waiting on b.
    return 6


executor = ThreadPoolExecutor(max_workers=2)
a = executor.submit(wait_on_b)
b = executor.submit(wait_on_a)

但遗憾的是,如果你在Flask里直接调用这个方法在涉及一些上下文操作的时候会因为丢失上下文而导致一些Flask的Function失效,如下面这样

from concurrent.futures import ThreadPoolExecutor
from app import db_connect
executor = ThreadPoolExecutor(1)
@app.before_request
def befre_request():
    _dict = {}
    for key, value in request.__dict__['environ'].items():
        if isinstance(value, str):
            _dict[key] = value
    executor.submit(visit_record, _dict)

def visit_record(_dict):
    t_visit = TVisit(v_addr=_dict['HTTP_X_FORWARDED_FOR'], v_user_agent=_dict['HTTP_USER_AGENT'],
                     v_path=_dict['PATH_INFO'], v_original=json.dumps(_dict), create_time=datetime.datetime.now())
    db_connect.session.add(t_visit)
    db_connect.session.commit()

在方法 visit_record 中涉及到插入数据,db_connect是使用Flask初始化的,因为丢失上下文会导致数据插入数据库失败

解决这个问题是方法是引入Flask的 copy_current_request_context,将上述代码改成如下即可解决问题

from concurrent.futures import ThreadPoolExecutor
from app import db_connect
# 改动一:引入copy_current_request_context
from flask import copy_current_request_context
executor = ThreadPoolExecutor(1)
@app.before_request
def befre_request():
    _dict = {}
    for key, value in request.__dict__['environ'].items():
        if isinstance(value, str):
            _dict[key] = value
    # 改动二:调用visit_record之前使用copy_current_request_context
    executor.submit(copy_current_request_context(visit_record), _dict)


def visit_record(_dict):
    t_visit = TVisit(v_addr=_dict['HTTP_X_FORWARDED_FOR'], v_user_agent=_dict['HTTP_USER_AGENT'],
                     v_path=_dict['PATH_INFO'], v_original=json.dumps(_dict), create_time=datetime.datetime.now())
    db_connect.session.add(t_visit)
    db_connect.session.commit()

Develop Technology Python 2019-10-16 17:45:43 location_on

Git - 不追踪文件变更

Git根目录下创建.gitignore文件,使用如下语法进行填写即可

# 过滤文件
/mtk/ 过滤整个文件夹
*.zip 过滤所有.zip文件
/mtk/do.c 过滤某个具体文件

# 添加文件
!*.zip
!/mtk/one.txt

如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先把本地缓存删除(改变成未被追踪状态),然后再提交

git rm -r --cached .
git add .
git commit -m 'update .gitignore'

Develop Base Git 2019-10-12 14:20:29 location_on

Linux - 查看管理所有用户技巧

查看所有用户使用如下指令

cat /etc/passwd
# 输出格式
Username:Password:UserID:GroupID:Comment:Home Directory:Shell
用户名:密码:用户ID:组ID:备注:用户目录:Shell命令起始名录

尝试使用一下,输出是正常的,但很不合适阅读,输出如下

[root@aliyun-vps chancel]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
……

这个时候我们使用Grep来做过滤同时使用column -t表格化输出

cat /etc/passwd|grep -v nologin|grep -v halt|grep -v shutdown|awk -F":" '{ print "ID:"$3 " | U:" $1" | G:"$4 }'|more|column -t

看看输出效果

[root@aliyun-vps chancel]# cat /etc/passwd|grep -v nologin|grep -v halt|grep -v shutdown|awk -F":" '{ print "ID:"$3 " | U:" $1" | G:"$4 }'|more|column -t
ID:0     |  U:root     |  G:0
ID:5     |  U:sync     |  G:0
ID:1000  |  U:chancel  |  G:1000

ID即用户ID,U即用户名,G即用户组ID,这样比原来清晰很多

Operating System Linux 2019-10-12 14:19:56 location_on

Linux - 命令定向输出到粘贴板

使用XSEL便可以复制命令行输出到粘贴板,便于分析一些在命令行里无法清楚判断的日志输出

# 复制直接输出的内容直接使用xsel
cat test.txt | xsel
# 复制类似journalctl这种系统日志输出(需要滚动)的日志则需要添加 -b 的标志
journalctl -xe | xsel -b

Operating System Linux 2019-10-12 14:19:26 location_on

Nginx - 强制Http跳转到Https

两种方法

  1. 使用return方法,推荐使用
    server{
     listen 80;
     server_name www.example.com;
     return 301 https://$server_name$request_uri;
    }
  2. 使用rewrite方法,不推荐使用
    server{
     listen 80;
     server_name www.example.com;
     rewrite ^(.*) https://$server_name$request_uri;
    }

Develop Base 2019-10-12 14:18:45 location_on

8 of 13 | A total of 128