.. _memo: 个人技术备忘录 💻 ===================================================================== .. 好记性不如烂笔头. - 中国谚语 Python --------------------------------------------------------------- .. code-block:: python # python起文件服务器 python3.4 -m http.server python -m SimpleHTTPServer # python2 python -u script.py # 刷新缓冲,执行脚本重定向结果到文件时候比较有用 python -u script.py | tee script.log # 打印脚本结果,同时输出到日志 (无缓冲可以立马看到输出) # logging FATAL(50) > ERROR(40) > WARNING(30) > INFO(20) > DEBUG(10) # 使用virtualenv制定python版本 virtualenv -p /usr/bin/python2.7 ENV2.7 # pyenv 安装多个版本的 python : https://github.com/pyenv/pyenv # pyenv-virtualenv https://github.com/pyenv/pyenv-virtualenv # mac install multiple version of python brew install pyenv pyenv-virtualenv pyenv install 3.6.4 # install python3.6.4 pyenv virtualenv 3.6.4 v3.6.4 pyenv activate v3.6.4 pyenv deactivate # 格式化 json,这个可以配置在 vim 里用来格式化当前 json 文本 cat some.json | python -m json.tool pip/easy_install --------------------------------------------------------------- .. code-block:: python # 服务器上有时候没有 root 权限可以试试 # https://stackoverflow.com/questions/7465445/how-to-install-python-modules-without-root-access # https://stackoverflow.com/questions/12332975/installing-python-module-within-code # pip install import pip def install(package): pip.main(['install', package]) # Example if __name__ == '__main__': install('argh') 有时候 pip 安装会比较慢可以更换为豆瓣的源,两种方式 1. ``pip install redis -i https://pypi.doubanio.com/simple`` 2. 或者修改全局 ``vi ~/.pip/pip.conf`` .. code-block:: shell [global] timeout = 60 index-url = http://pypi.douban.com/simple trusted-host = pypi.douban.com IPython --------------------------------------------------------------- .. code-block:: sh # ipython 如何使用 autoreload,每次重新修改了文件都得重新重启 ipython 很麻烦,解决方式 # https://support.enthought.com/hc/en-us/articles/204469240-Jupyter-IPython-After-editing-a-module-changes-are-not-effective-without-kernel-restart # https://stackoverflow.com/questions/1254370/reimport-a-module-in-python-while-interactive # http://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html In [1]: %load_ext autoreload In [2]: %autoreload 2 .. code-block:: python3 # -*- coding: utf-8 -*- # ~/.ipython/profile_default/startup/startup.py # Ned's .startup.py file ipython 启动加载文件,用来导入一些自定义函数或者模块,方便调试 # http://stackoverflow.com/questions/11124578/automatically-import-modules-when-entering-the-python-or-ipython-interpreter print("(.startup.py)") import datetime as dt import os import pprint import re import sys import time import json import requests as req try: import matplotlib.pyplot as plt import pandas as pd from pandas import Series, DataFrame import numpy as np except ImportError: pass print("(imported datetime, os, pprint, re, sys, time, json)") def _json_dumps(dict_data, indent=4): """用来处理一些包含中文的 json 输出""" print(json.dumps(dict_data, indent=indent, ensure_ascii=False)) def _repr_dict(d): """https://stackoverflow.com/questions/25118698/print-python-dictionary-with-utf8-values""" print('{%s}' % ',\n'.join("'%s': '%s'" % pair for pair in d.iteritems())) def _json_dumps(dict_data, indent=4): """用来处理一些包含中文的 json 输出""" print(json.dumps(dict_data, indent=indent, ensure_ascii=False)) repr_dict = _repr_dict pp = pprint.pprint json_dumps = _json_dumps .. code-block:: sh # http://shawnleezx.github.io/blog/2015/08/03/some-notes-on-ipython-startup-script/ """ !!! 注意,如果遇到了 TypeError: super(type, obj): obj must be an instance or subtype of type 请禁用 autoreload, http://thomas-cokelaer.info/blog/2011/09/382/ """ from IPython import get_ipython ipython = get_ipython() # ipython.magic("pylab") ipython.magic("load_ext autoreload") ipython.magic("autoreload 2") # Ipython 技巧,如何查询文档,比如 time.time 方法的文档 # https://jakevdp.github.io/PythonDataScienceHandbook/01.01-help-and-documentation.html >>> import time >>> time.time? # 回车之后可以输出该函数的 docstring 文档 >>> time.time?? # 回车之后可以输出该函数的定义 Ipdb --------------------------------------------------------------- .. code-block:: sh # ~/.pdbrc # https://github.com/gotcha/ipdb/issues/111 import os alias kk os._exit(0) # 如果不幸在循环里打了断点,可以用 os._exit(0) 跳出 alias pd for k in sorted(%1.keys()): print "%s: %s" % (k, (%1[k])) # https://stackoverflow.com/questions/21123473/how-do-i-manipulate-a-variable-whose-name-conflicts-with-pdb-commands # 如果 pdb 里的内置命令和内置函数冲突了,可以加上 ! 使用内置函数 !next(iter) Chrome(Mac) --------------------------------------------------------------- .. code-block:: sh # 使用 comamnd + l 可以立即定位到 url 输入框 # 使用 vimium 或者 surfingkeys 插件可以用 vim 的模式操作 chrome # 用 vimium 如何不用鼠标从 url 输入框回到网页: https://superuser.com/questions/324266/google-chrome-mac-set-keyboard-focus-from-address-bar-back-to-page/324267#324267 https://xavierchow.github.io/2016/03/07/vimium-leave-address-bar/ # 清理 dns cache, https://superuser.com/questions/203674/how-to-clear-flush-the-dns-cache-in-google-chrome Navigate to chrome://net-internals/#dns # and press the "Clear host cache" button. # 收藏夹。注意分类收藏,否则后来会收藏多了比较乱。使用 surfingkeys ab (add bookmark) 和 gb(收藏夹管理) 可以快速操作 # 黑科技:如何chrome 证书认证(不推荐) 在网页中输入 thisisunsafe 或者 badidea 就可以了 MacOS --------------------------------------------------------------- .. code-block:: python # NOTE: 使用『时间机器』定期备份你的mac 是一个好习惯,笔者买了一个移动硬盘用来定期备份 # 文件字符串批量替换,git项目里替换的时候注意指定文件类型,防止破坏git信息 # 注意 mac 的 sed 命令和 linux 有区别(比如mac sed -i 后必须有参数) https://unix.stackexchange.com/questions/13711/differences-between-sed-on-mac-osx-and-other-standard-sed # 可以使用 brew install gnu-sed 替换,然后使用 gsed 命令替代 find . -name \*.py -exec sed -i '' 's/old/new/g' {} \; # copy that data into the system’s paste buffer cat file.txt | pbcopy # The pbpaste command lets you take data from the system’s paste buffer and write it to standard out. pbcopy < birthday.txt pbpaste | ag name pbpaste > filename # updatedb https://superuser.com/questions/109590/whats-the-equivalent-of-linuxs-updatedb-command-for-the-mac sudo /usr/libexec/locate.updatedb # homebrew 更换源, https://maomihz.com/2016/06/tutorial-6/ cd /usr/local git remote set-url origin git://mirrors.ustc.edu.cn/brew.git cd /usr/local/Library/Taps/homebrew/homebrew-core git remote set-url origin git://mirrors.ustc.edu.cn/homebrew-core.git # 从终端查 wifi 密码, https://apple.stackexchange.com/questions/176119/how-to-access-the-wi-fi-password-through-terminal security find-generic-password -ga "ROUTERNAME" | grep "password:" # XXX.APP已损坏,打不开.你应该将它移到废纸篓 MACOS 10.12 SIERRA,允许“任何来源” https://zhuanlan.zhihu.com/p/135948430 sudo spctl --master-disable # 使用 mounty 挂载 ntfs 盘,Item "file.mov" is used by Mac OS X and cannot be opened. # https://apple.stackexchange.com/questions/136157/mov-file-in-external-hd-greyed-out-and-wont-open-this-item-is-used-by-mac-o?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa cd /Volumes/[drive name] xattr -d com.apple.FinderInfo * # or SetFile -c "" -t "" path/to/file.mov # mac 使用命令挂载 diskutil mount /dev/disk1s2 diskutil unmount /dev/disk1s2 # 使用 rmtrash 删除到 trash,防止危险的 rm 删除命令找不回来。在 bashrc or zshrc alias rm='rmtrash ' # 如果是 linux 用户,可以使用 safe-rm https://github.com/kaelzhang/shell-safe-rm # 删除的文件会放到 $HOME/.Trash 方便恢复 brew install rmtrash # npm install -g safe-rm; alias rm='safe-rm' # 如何在文件更新之后自动刷新浏览器,需要首先 pip 安装 when-changed alias flush_watch_refresh_chrome=" when-changed -v -r -1 -s ./ osascript -e 'tell application \"Google Chrome\" to tell the active tab of its first window to reload' " # 如何启用三指拖移(新版本把改设置移动到了辅助功能,使用三指移动可以方便地移动窗口,一般我会启用提高效率) 辅助功能 -> 鼠标与触控板 -> 触控板选项 -> 启用拖移 (之后就能直接三指翻译单词了) # 如何解决 mac 突然没有声音的问题(系统 bug,音频守护进程 coreaudiod出了问题) sudo killall coreaudiod # mac 如何使用 realpath 显示绝对路径, https://stackoverflow.com/questions/3572030/bash-script-absolute-path-with-os-x # brew install coreutils grealpath file # mac trackpad 蓝牙频繁掉线问题。尝试使用 5G wifi 而不是 2.4G # https://apple.stackexchange.com/questions/321948/why-does-my-magic-trackpad-2-randomly-disconnect-and-stop-clicking # 软件:pathfinder 如何增加 隔空投送 airdrop 分享文件 https://support.cocoatech.com/discussions/problems/126873-full-airdrop-sharing-is-here-for-pf8-and-pf7 # mac 压缩之后去掉 "_MACOSX" 隐藏文件。https://stackoverflow.com/questions/10924236/mac-zip-compress-without-macosx-folder zip -d filename.zip __MACOSX/\* # 解压 windows zip 乱码。https://www.jianshu.com/p/460f9307dadf brew install unar unar -e GBK xx中文xx.zip # 删除旧文件 https://tecadmin.net/delete-files-older-x-days/ find /var/log -name "*.log" -type f -mtime +30 # 找到 30 天之前修改的文件,指定文件类型 为 log find /var/log -name "*.log" -type f -mtime +30 -delete # 执行删除 find /opt/backup -type f -mtime +30 # hide or show desktop icon for presentation 隐藏桌面图标 alias hide_desktop_icon='defaults write com.apple.finder CreateDesktop -bool false; killall Finder' alias show_desktop_icon='defaults write com.apple.finder CreateDesktop -bool true; killall Finder' # mac https://apple.stackexchange.com/questions/54329/can-i-get-the-cpu-temperature-and-fan-speed-from-the-command-line-in-os-x gem install iStats # need istats all # mac 休眠 https://www.jianshu.com/p/ec888c3e33dd sudo shutdown -s +10 # 10分钟后休眠 # mac https://superuser.com/questions/273756/how-to-change-default-app-for-all-files-of-particular-file-type-through-terminal # https://chainsawonatireswing.com/2012/09/19/changing-default-applications-on-a-mac-using-the-command-line-then-a-shell-script/ brew install duti # 安装 duti osascript -e 'id of app "calibre.app"' # https://www.hexnode.com/mobile-device-management/help/how-to-find-the-bundle-id-of-an-application-on-mac/ duti -x sh # 获取 .sh 文件的默认打开软件,最后一行是id duti -s io.brackets.appshell .md all # 用该 id 的软件打开所有的 md 文件 osascript -e 'id of app "ebook-viewer.app"' # 安装 calibre 之后,找到附带的电子书浏览软件 id duti -s com.calibre-ebook.ebook-viewer .mobi all # 用 ebook-viewer 打开所有的 mobi 如何发送 mac 通知,可以用来做提示 .. code-block:: python # https://stackoverflow.com/questions/17651017/python-post-osx-notification # 配合 crontab 可以用来做一个简单的定时任务提醒功能 57-59 17 * * * python ~/.tmp/noti.py # ~/.tmp/noti.py import os def notify(title, text): os.system(""" osascript -e 'say "家里放点音乐吧"' """) os.system(""" osascript -e 'display notification "{}" with title "{}"' """.format(text, title)) notify("开会啦", "Go Go Go !!!") 增加终端下光标的移动速度(⭐️ 非常好用): .. code-block:: shell # mac: 系统设置-> 键盘 -> 修改按键重复到最快,重复前延迟最短。可以让光标在终端里移动更快 (推荐下边的命令修改更快) # 增加 terminal 光标移动速度, https://stackoverflow.com/questions/4489885/how-can-i-increase-the-cursor-speed-in-terminal # 终端执行以下三个 defaults 命令后必须重启(亲测有效,速度飞起! 😄) https://medium.com/@juanpaulo/set-blazingly-fast-key-repeats-a87c808ad01d # Disable press-and-hold for keys in favor of key repeat defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false # Set a blazingly fast keyboard repeat rate defaults write NSGlobalDomain KeyRepeat -int 1 # 默认值 2,设置成 1 合适,设置成 0 就太快了,翻页刷新有问题 defaults write NSGlobalDomain InitialKeyRepeat -int 10 如何命令行格式化u盘: .. code-block:: shell # https://superuser.com/questions/527657/how-do-you-format-a-2-gb-sd-card-to-fat32-preferably-with-disk-utility # 找到你的u 盘 diskutil list # 格式化 u 盘,注意 UDISKNAME 必须大写。最后的 /dev/disk2 是上一步找到的 u 盘,千万别写错了 sudo diskutil eraseDisk FAT32 UDISKNAME MBRFormat /dev/disk2 增加 time machine 备份速度: .. code-block:: shell # https://huataihuang.gitbooks.io/cloud-atlas/content/develop/mac/time_machine_backup_speed.html sudo sysctl debug.lowpri_throttle_enabled=0 # 关闭限流 sudo sysctl debug.lowpri_throttle_enabled=1 # 恢复限流 SSH ------------- 二次验证自动登录跳板机脚本,根据你的密码和服务器配置修改即可。 .. code-block:: python #!/bin/sh # 有二次验证登录跳板机的时候比较麻烦,可以用这个脚本自动登录跳板机 参考:https://juejin.im/post/5ce760cef265da1b6e657d6f # brew install expect # brew install oath-toolkit # {user} {ip} {yourpassword} {server_qr_token} 替换成对应的 用户名、ip、密码、服务器秘钥 (密码建议定期更换防止安全风险) export LC_CTYPE="en_US.UTF-8" expect -c " spawn ssh user@ip -p22 set timeout 3 expect \"user@ip's password:\" set password yourpassword set token \"`oathtool --totp -b -d 6 server_qr_token`\" send \"\$password\$token\r\" interact " Mac 蓝牙耳机(自用索尼 wi1000x) --------------------------------------------------------------- 如何给 Macbook 开启 Apt-X 蓝牙音质果更高 - https://www.jianshu.com/p/a1efa561ed9e - https://gist.github.com/dvf/3771e58085568559c429d05ccc339219 注意:mac有一个 bug 至今没有修复,cpu 占用高的时候使用蓝牙耳机可能会被莫名其妙修改平衡。声音一边大一边小,去设置-声音里调整一下就好。 `macbook-pro-bluetooth-audio-balance-keeps-changing-by-itself `_ Proxy --------------------------------------------------------------- mac电脑下设置socks5代理 https://blog.csdn.net/fafa211/article/details/78387899 Oh My Zsh --------------------------------------------------------------- .. code-block:: shell # Powerlevel9k 是一个强大的 zsh 主题 # iTerm2 + Oh My Zsh + Solarized color scheme + Meslo powerline font + [Powerlevel9k] - (macOS) # https://gist.github.com/kevin-smets/8568070 # https://gist.github.com/dogrocker/1efb8fd9427779c827058f873b94df95 # 安装自动补全插件 git clone https://github.com/zsh-users/zsh-autosuggestions.git $ZSH_CUSTOM/plugins/zsh-autosuggestions git clone https://github.com/zsh-users/zsh-syntax-highlighting.git $ZSH_CUSTOM/plugins/zsh-syntax-highlighting # nvi ~/.zshrc plugins=(git zsh-autosuggestions zsh-syntax-highlighting) # 如何复制上一条命令, https://apple.stackexchange.com/questions/110343/copy-last-command-in-terminal alias lcc='fc -ln -1 | awk "{\$1=\$1}1" ORS="" | pbcopy ' # 报错:_git:58: _git_commands: function definition file not found # 解决方式:rm ~/.zcompdump*; rm ~/.zplug/zcompdump # https://github.com/robbyrussell/oh-my-zsh/issues/3996 # rm ~/.zcompdump; exec zsh -l # https://github.com/ohmyzsh/ohmyzsh/issues/3996 Linux(centos/ubuntu) --------------------------------------------------------------- .. code-block:: python # 查看版本 lsb_release -a # virtual box虚拟机和windows主机共享目录方法:安装增强工具;win主机设置共享目录例如ubuntu_share;在ubuntu里建立/mnt/share后使用命令: sudo mount -t vboxsf ubuntu_share /mnt/share/ # 映射capslock 为 ctrl setxkbmap -layout us -option ctrl:nocaps # 文件字符串批量替换(危险操作最好有 git 版本控制方便回滚) grep oldString -rl /path | xargs sed -i "s/oldString/newString/g" # 删除多个文件中包含 patter 的指定行。比如递归删除包含 sleep 的行 (注意这种危险操作最好有 git 版本控制,方便回滚) # https://stackoverflow.com/questions/1182756/remove-line-of-text-from-multiple-files-in-linux find . -name "*.go" -type f | xargs sed -i -e '/sleep/d' # 递归删除某一类型文件 find . -name "*.bak" -type f -delete # 监控某一日志文件变化 tail -f t.log # 类似mac pbcopy, apt-get install xsel cat README.TXT | xsel cat README.TXT | xsel -b # 如有问题可以试试-b选项 xsel < README.TXT # 将readme.txt的文本放入剪贴板 xsel -c # 清空剪贴板 # 可以把代码文件贴到paste.ubuntu.com共享,此命令返回一个网址 # sudo apt-get install pastebinit; sudo pip install configobj pastebinit -i [filename] # json格式化输出 echo '{"foo": "lorem", "bar": "ipsum"}' | python -m json.tool python -m json.tool my_json.json # 或者apt-get intsall jq jq . <<< '{ "foo": "lorem", "bar": "ipsum" }' # 进程相关 dmesg | egrep -i -B100 'killed process' # 查看被杀死进程信息 # linux 批量杀掉筛选进程(比如定时脚本多个同时执行,最好限制) https://blog.csdn.net/weiyichenlun/article/details/59108463 ps -ef | grep main.py | grep -v grep | awk '{print $2}' | xargs kill -9 # scp scp someuser@192.168.199.1:/home/someuser/file ./ # 远程机器拷贝到本机 scp ./file someuser@192.168.199.1:/home/someuser/ # 拷贝到远程机器 # tar tar zxvf FileName.tar.gz # 解压 tar zcvf FileName.tar.gz DirName # 压缩 # 监控文件变动并且自动增量同步本地文件到服务器对应文件夹(需要先安装 when-changed) when-changed -r -v -1 . rsync -avh --exclude='.git/' --exclude='mydoc/' --exclude='output/' /Users/pegasus/work/code/ XXX@ip:/home/pegasus/work/code/ 代码搜索用Ag(the silversearcher)/rg, 比ack快 .. code-block:: shell # 安装 sudo apt-get install silversearcher-ag # ubuntu brew install ag # mac ag string dir/ # search dir ag readme$ # regular expression ag -Q .rb # Literal Expression Searches, search for the exact pattern。这个选项很有用,特殊字符不用转义了 ag string -l # Listing Files (-l) ag string -i # Case Insensitive Searches (-i) ag string -G py$ # 搜索应py结尾的文件 (指定文件类型) ag readme -l --ignore-dir=railties/lib # 忽略文件夹 ag readme -l --ignore-dir="*.rb" # 忽略特性类型文件 .agignore # 用来忽略一些vcs,git等文件。 Centos ------------------------------------------------------------- .. code-block:: shell # 如何搜索和安装指定版本 # https://unix.stackexchange.com/questions/151689/how-can-i-instruct-yum-to-install-a-specific-version-of-package-x yum --showduplicates list golang yum install package-version crontab ------------------------------------------------------------- 分、时、日、月、周 .. code-block:: python # 记得bashrc里边 EXPORT EDITOR=vim export PYTHONIOENCODING=UTF-8 # crontab注意:绝对路径;环境变量; 0 */5 * * * python -u /root/wechannel/crawler/sougou_wechat/sougou.py >> /root/wechannel/crawler/sougou_wechat/log 2>&1 */5 * * * * /root/pyhome/crawler/lagou/changeip.sh >> /root/pyhome/crawler/lagou/ip.log 2>&1 # 一个 crontab 表达式工具 - https://tooltt.com/crontab/ - https://tool.lu/crontab/ 可以用如下方式执行依赖其他模块的python脚本,用run.sh执行run.py,记得chmod +x可执行权限,运行前执行下sh脚本测试能否成功 .. code-block:: sh #!/usr/bin/env bash PREFIX=$(cd "$(dirname "$0")"; pwd) cd $PREFIX source ~/.bashrc python -u run.py # -u 参数强制刷新输出 date 对于python脚本,可以用如下方式保证同一时间只有一个脚本在运行(一些定时任务同一台机器上多个同时跑可能有问题),可以用 如下方式限制。(多个机器上应该用分布式锁) .. code-block:: shell #!/usr/bin/env python # -*- coding:utf-8 -*- import time # https://stackoverflow.com/questions/380870/make-sure-only-a-single-instance-of-a-program-is-running # 更好的方式使用 tendo # pip install tendo from tendo import singleton me = singleton.SingleInstance() # will sys.exit(-1) if other instance is running def main(): time.sleep(10) print(time.time()) if __name__ == '__main__': main() * `《crontab快速参考》 `_ Iterm2/Terminal ------------------------------------------------------------- .. code-block:: sh # https://stackoverflow.com/questions/11913990/iterm2-keyboard-shortcut-for-moving-tabs-around # Preferences/Keys 自定义配置使用 Cmd +jk 来在 Iterm2 tab 前后移动,模仿 vim 键位 # 如何防止 command+w 意外关闭导致工作丢失,这里可以如下设置,每次关闭提醒 # Settings -> Profiles -> Session -> Prompt before closing 勾选 Always # 如何使用 rz/sz 传文件 https://segmentfault.com/a/1190000012166969 # 如何使用 iterm2 it2copy 从 服务器上用 vim 拷贝文件 # https://stackoverflow.com/questions/10694516/vim-copy-mac-over-ssh/10703012 1. 安装 iTerm2 Utilities 到服务器。iTerm2 -> Install shell Integratio。后边是 bash or zsh,根据你用的 shell 选择 curl -L https://iterm2.com/shell_integration/install_shell_integration_and_utilities.sh | zsh 2. 重新登录之后 it2copy 生效 3. 在 vim visual 模式选择之后 执行 `:w !it2copy` 即可。或这直接 cat file.txt | it2copy # 终端输出乱序。有时候有一些脚本或者软件可能会修改终端配置但是失败后又没有恢复,导致输出乱序,解决如下 `stty sane` 或者 `reset` Tmux ------------------------------------------------------------- .. code-block:: sh # 建议直接用 https://github.com/gpakosz/.tmux 这个强大的 tmux 配置(oh-my-tmux) # 不过注意,如果一开始 tmux.conf.local 里的命令执行失败(比如curl 网络失败)可能导致插件加载失败,注意排查 # https://wiki.archlinux.org/index.php/tmux tmux rename -t oriname newname tmux att -t name -d # -d 不同窗口全屏 # 如果手贱在本机tmux里又ssh到服务器又进入服务器的tmux怎么办(退出 tmux 套娃) c-b c-b d # 如果升级了 tmux 之后,使用 tmux 出现 tmux server exited unexpectedly 尝试删除 /tmp 里的 tmux 临时文件 # https://github.com/tmux/tmux/issues/2376 # 技巧:tmux 如何在多个 pane 执行一样的命令。先执行 ctrl + b : ctrl + b : setw synchronize-panes on setw synchronize-panes off # Vim style pane selection bind -n C-h select-pane -L bind -n C-j select-pane -D bind -n C-k select-pane -U bind -n C-l select-pane -R # https://stackoverflow.com/questions/22138211/how-do-i-disconnect-all-other-users-in-tmux tmux a -dt # 如何 ssh 后自动 attach 到某个 session。编辑你的 .bashrc or .zshrc if [[ "$TMUX" == "" ]] && [[ "$SSH_CONNECTION" != "" ]]; then # Attempt to discover a detached session and attach it, else create a new session WHOAMI="lens" # attach 的 session 名称 if tmux has-session -t $WHOAMI 2>/dev/null; then tmux -2 attach-session -t $WHOAMI else tmux -2 new-session -s $WHOAMI fi fi # 或者 if [[ -z "$TMUX" ]] && [ "$SSH_CONNECTION" != "" ]; then SESSION_NAME="sessionname" tmux attach-session -t $SESSION_NAME || tmux new-session -s $SESSION_NAME fi # 问题:Tmux resurrect file not found! 。新版本应该是放到了 ~/.local/share/tmux/resurrect 。老版本在~/.tmux/resurrect function tmux-resurrect-reset-last() { cd ~/.local/share/tmux/resurrect && \ ln -f -s $(/bin/ls -t tmux_resurrect_*.txt | head -n 1) last && \ /bin/ls -l last } # use prefix + m zoom and unzoom panes. https://tao-of-tmux.readthedocs.io/en/latest/manuscript/07-pane.html bind-key -T prefix m resize-pane -Z SSH ------------------------------------------------------------- .. code-block:: python # https://superuser.com/questions/98562/way-to-avoid-ssh-connection-timeout-freezing-of-gnome-terminal/98565#98565 Press Enter, ~, . one after the other to disconnect from a frozen session. # https://unix.stackexchange.com/questions/176547/copy-only-file-details-file-name-size-time-from-remote-machine-in-unix ssh remotemachine "ls -l /opt/apache../webapps/Context" # 使用 paramiko 库可以实现 ssh client 功能 # https://www.digitalocean.com/community/tutorials/how-to-use-fabric-to-automate-administration-tasks-and-deployments Fabric ------------------------------------------------------------- 可以用 Fabric 实现一些自动化控制服务器功能。示例 fabfile.py .. code-block:: python # -*- coding: utf-8 -*- import os from fabric.api import run, env, get, local """ 需求:经常忘记开发机 build 完go 二进制文件以后 scp 到本地,导致有时候部署还是老的二进制文件。 功能: 实现监听开发机的二进制文件变动,每一次和本地文件对比,如果有开发机二进制文件大小变了,就拷贝到本地来。 # pip install fabric==1.14.0 # brew install watch mac 下用 watch 用来定期执行命令 watch -n 60 ls 比如每分钟检查一下开发机上的 FaceFusionServer 是否重新 build 了,然后拉取到本地,可以执行 watch -n 30 fab monitor_facefusion_server monitor_uploadserver 1. http://www.bjhee.com/fabric.html """ class Bcolors: HEADER = '\033[95m' OKBLUE = '\033[94m' OKGREEN = '\033[92m' WARNING = '\033[93m' FAIL = '\033[91m' ENDC = '\033[0m' BOLD = '\033[1m' UNDERLINE = '\033[4m' env.hosts = ['dev'] env.use_ssh_config = True env.password = "" def who(): run('whoami') def is_change(remote_path, local_path): """ 根据 md5 判断是否变化,注意 centos 和 mac 命令和结果格式不同 centos: md5sum UploadServer e4fccc07eafc7ef97d436c50546e352b UploadServer mac: md5 UploadServer MD5 (UploadServer) = e4fccc07eafc7ef97d436c50546e352b :param remote_path: absolute remote server path :param local_path: local path """ output = run("md5sum {}".format(remote_path)) # 请保证路径存在,不会判断 remote_md5 = output.split()[0].strip() if not os.path.exists(local_path): # 第一次本地没有文件直接拉取 return True local_output = local("md5 {}".format(local_path), capture=True) local_md5 = local_output.split()[-1].strip() return remote_md5 != local_md5 def monitor_uploadserver(): remote_path = "/user/work/UploadServer" local_path = "./UploadServer" if is_change(remote_path, local_path): # 变化了就复制到本地 get(remote, local),存在会覆盖 print(Bcolors.WARNING + "===========%s file changed=========" + Bcolors.ENDC) get(remote_path, local_path) local("chmod +x {}".format(local_path)) else: print(Bcolors.HEADER + local_path + " not change" + Bcolors.ENDC) Makefile ------------------------------------------------------------- .. code-block:: sh # 如何设置子进程环境变量 https://stackoverflow.com/questions/23843106/how-to-set-child-process-environment-variable-in-makefile test: export NODE_ENV = test Git ------------------------------------------------------------- .. code-block:: python # .gitconfig配置用如下配置可以使用pycharm的diff和merge工具(已经安装pycharm) [diff] tool = pycharm [difftool "pycharm"] cmd = /usr/local/bin/charm diff "$LOCAL" "$REMOTE" && echo "Press enter to continue..." && read [merge] tool = pycharm keepBackup = false [mergetool "pycharm"] cmd = /usr/local/bin/charm merge "$LOCAL" "$REMOTE" "$BASE" "$MERGED" # https://stackoverflow.com/questions/34549040/git-not-displaying-unicode-file-names # git 显示中文文件名,如果你的文件名有中文会好看很多 git config --global core.quotePath false # 用来review: git log --since=1.days --committer=PegasusWang --author=PegasusWang git log --since="6am" # 查看当天提交 git diff commit1 commit2 # 冲突以后使用远端的版本: NOTE:注意在 git merge 和 git rebase 中 ours/theirs 含义相反! # rebase 场景下,theirs 实际表示的是当前分之 # merge 场景下相反,theirs 表示的是远端分之 # https://stackoverflow.com/questions/16825849/choose-git-merge-strategy-for-specific-files-ours-mine-theirs # https://bitmingw.com/2017/02/16/git-merge-rebase-ours-and-theirs/ git checkout --theirs templates/efmp/campaign.mako # 防止http协议每次都要输入密码: git config --global credential.helper 'cache --timeout=36000000' #秒数 # 暂存和恢复,当我们需要切分支又暂时不想 git add,可以先把目前的修改暂存起来 git stash # 暂存当前的修改 git stash apply git stash apply stash@{1} git stash pop # 重新应用储藏并且从堆栈中移走 # 显示 git stash 内容 https://stackoverflow.com/questions/7677736/git-diff-against-a-stash git stash list # 展示当前的所有 stash 列表 git stash show -p # see the most recent stash git stash show -p stash@{1} # 删除远程分之 git push origin --delete {the_remote_branch} # 手残 add 完以后输入错了 commit 信息 git commit --amend # 修改文件内容并合并到上一次的commit变更当中。比如发现没有修改完全,又改了代码,可以修改之后 add 然后执行 git commit --amend --no-edit # 类似的还可以修改上一个提交者的名字 https://stackoverflow.com/questions/750172/how-to-change-the-author-and-committer-name-and-e-mail-of-multiple-commits-in-gi git config --global user.name "you name" git config --global user.email you@domain.com git commit --amend --reset-author # 如果想要修改多个历史提交的 commit 信息,可以使用 git rebase -i 交互式修改。对应的提交行使用 reword 就可以 # 撤销 add (暂存),此时还没有 commit。比如 add 了不该 add 的文件 git reset -- file git reset # 撤销所有的 add # 撤销修改 git checkout -- file # 手残pull错了分支就(pull是先fetch然后merge)。或者 revert 一个失误的 merge git reset --hard HEAD~ # 如果 pull 产生了 冲突,可以撤销。 git merge --abort # git rebase 同样可以 git rebase --abort # How to revert Git repository to a previous commit?, https://stackoverflow.com/questions/4114095/how-to-revert-git-repository-to-a-previous-commit git reset --hard 0d1d7fc32 # 手残直接在master分之改了并且add了 git reset --soft HEAD^ git branch new_branch # 切到一个新分支去 commit git checkout new_branch git commit -a -m "..." # 或者 git reset --soft HEAD^ git stash git checkout new_branch git stash pop # 如果改了master但是没有add比较简单,三步走 git stash git checkout -b new_branch git stash pop # rename branch git branch -m git branch -m # rename the current branch # 指定文件类型diff git diff master -- '*.c' '*.h' # 带有上下文的diff git diff master --no-prefix -U999 # undo add git reset git reset # undo all # undo git reset https://stackoverflow.com/questions/2510276/how-to-undo-git-reset git reset 'HEAD@{1}' # 查看add后的diff git diff --staged # http://weizhifeng.net/git-rebase.html # rebase改变历史, 永远不要用在master分之,别人有可能使用你的分之时也不要用 # only change history for commits that have not yet been pushed # master has changed since I stared my feature branch, and I want bo bring my branch up to date with master. - Dont't merge. rebase # rebase: finds the merge base; cherry-picks all commits; reassigns the branch pointer. # then git push -f # git rebase --abort # 全局 ignore, 对于不同编辑器协作的人比较有用,或者用来单独忽略一些自己建立的测试文件等。 # NOTE: git 支持每个子文件夹下有一个自己的 .gitignore,文件路径也是相对当前文件夹 git config --global core.excludesfile ~/.gitignore_global # 全局忽略一些文件 # 拉取别人远程分支,在 .git/config 里配置好 git fetch somebody somebranch git checkout -b somebranch origin/somebranch # prune all the dead branches from all the remotes # https://stackoverflow.com/questions/17933401/how-do-i-remove-deleted-branch-names-from-autocomplete?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa git fetch --prune --all # 清理本地本删除的远程分之,补全的时候很干净,没有已经删除的分之 # https://stackoverflow.com/questions/1274057/how-to-make-git-forget-about-a-file-that-was-tracked-but-is-now-in-gitignore # https://wildlyinaccurate.com/git-ignore-changes-in-already-tracked-files/ # 如果一个文件已经被 git 跟踪但是你之后又不想提交针对它的修改了,可以这么做(比如我想修改一些配置,本地 debug 等) git update-index --assume-unchanged # 忽略一个已经 tracked 的文件,修改后不会被 commit git update-index --no-assume-unchanged # undo 上一步 # 那如何列出这些文件呢? https://stackoverflow.com/questions/2363197/can-i-get-a-list-of-files-marked-assume-unchanged git ls-files -v | grep '^[[:lower:]]' # https://stackoverflow.com/questions/48341920/git-branch-command-behaves-like-less # 禁止 git brach 的时候使用交互式 git config --global pager.branch false # git rm file and add, https://stackoverflow.com/questions/9591407/unstage-a-deleted-file-in-git/9591612 # this restores the file status in the index git reset -- # then check out a copy from the index git checkout -- # 如何恢复一个已经删除的分之, https://stackoverflow.com/questions/3640764/can-i-recover-a-branch-after-its-deletion-in-git git reflog # 查找对应 commit hash git checkout -b branch-name hash # git diff 代码显示 tab 为 4 个空格,比如看 go 代码的时候,git diff 显示 8 个 # https://stackoverflow.com/questions/10581093/setting-tabwidth-to-4-in-git-show-git-diff git config --global core.pager 'less -x1,5' # git 如何使用不同的 committer,除了每个项目和全局可以设置 gitconfig 里的 user 外,可以使用如下方式 # https://stackoverflow.com/questions/4220416/can-i-specify-multiple-users-for-myself-in-gitconfig # global config ~/.gitconfig [user] name = John Doe email = john@doe.tld [includeIf "gitdir:~/work/"] path = ~/work/.gitconfig # ~/work/.gitconfig [user] email = john.doe@company.tld # 从提交历史搜索字符串,比如提交历史中引入了一个新的函数,可以通过这个方式搜索 # https://stackoverflow.com/questions/5816134/how-to-find-the-git-commit-that-introduced-a-string-in-any-branch git log -S 'hello world' --source --all # 统计xx某某提交了多少代码 git log --author="xxx" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' # 修改上一次提交人。比如一开始 git commiter 配置错了。https://stackoverflow.com/questions/3042437/how-to-change-the-commit-author-for-one-specific-commit git commit --amend --author="Author Name " --no-edit # tags 功能(比如从一个源码的 tag 构建) https://stackoverflow.com/questions/35979642/what-is-git-tag-how-to-create-tags-how-to-checkout-git-remote-tags git tag -l # 显示所有 tag git checkout tags/ -b # 生成和应用 patch, https://stackoverflow.com/questions/28192623/create-patch-or-diff-file-from-git-repository-and-apply-it-to-another-different git diff tag1..tag2 > mypatch.patch git apply mypatch.patch # 删除当前文件夹 git 未跟踪的文件 https://stackoverflow.com/questions/61212/how-do-i-remove-local-untracked-files-from-the-current-git-working-tree git clean -f # 注意危险操作提前确认文件确实可以删除 Git 删除大文件 ---------------------------- Git 只适合代码文本管理,如果误提交了一个二进制文件或者视频等文件将会导致 git 仓库变得非常大。 你应该在首次提交代码的时候就是用 gitignore 忽略掉大文件,如果已经误提交了,直接删除文件并不会删除 git 历史中的记录。 需要使用专门的工具来进行删除,目前官方推荐使用 git-filter-repo 了,不再推荐使用 git filter-branch。 .. code-block:: shell # ⭐️ git 如何删除提交历史中的大文件(比如很多新手误提交了一个二进制或者视频等大文件) # git 注意不要把二进制大文件,视频文件等放入到版本库,可能会导致 .git 非常大,删了也无济于事 find . -executable -type f >>.gitignore # https://stackoverflow.com/questions/5711120/gitignore-without-binary-files # git 历史删除大文件。如果你提交了大文件,即使你git rm删除了也会留在 git 的历史记录中,导致.git 文件夹很大 # https://stackoverflow.com/questions/8083282/how-do-i-remove-a-big-file-wrongly-committed-in-git # git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch path_to_file" HEAD # ⭐️ 推荐使用 git-filter-repo # https://stackoverflow.com/questions/2100907/how-to-remove-delete-a-large-file-from-commit-history-in-the-git-repository # https://www.jianshu.com/p/03bf1bc1b543 pip install git-filter-repo # 安装 git filter-repo --invert-paths --path-match YOUR_BIG_FILE # 从提交历史删除大文件 git push -f origin master # 因为修改了提交历史,可能需要临时放开一下 master 权限,强行 push 一次 Git工作流 ------------ .. code-block:: shell git checkout master # 切到master git pull origin master # 拉取更新 git checkout -b newbranch # 新建分之,名称最好起个有意义的,比如jira号等 # 开发中。。。 git fetch origin master # fetch master git rebase origin/master # # 开发完成等待合并到master,推荐使用 rebase 保持线性的提交历史,但是记住不要在公众分之搞,如果有无意义的提交也可以用 rebase -i 压缩提交 git rebase -i origin/master git checkout master git merge newbranch git push origin master # 压缩提交 git rebase -i HEAD~~ # 最近两次提交 Git hook ------------ 比如我们要在每次 commit 之前运行下单测,进入项目的 .git/hooks 目录, "cp pre-commit.sample pre-commit" 修改内容如下: .. code-block:: bash #!/bin/sh if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi # Redirect output to stderr. exec 1>&2 if /your/path/bin/test: # 这里添加需要运行的测试脚本 then exit 0 else exit 1 fi # If there are whitespace errors, print the offending file names and fail. exec git diff-index --check --cached $against -- Gitub ------------ 克隆 Github 仓库时遇到报措 kex_exchange_identification: Connection closed by remote host。执行 ``ssh -T git@github.com`` kex_exchange_identification: Connection closed by remote host。 可能是因为某些🪜封禁了 github 端口 22 的连接。修改端口: .. code-block:: bash Host github.com HostName ssh.github.com User git Port 443 vim/neovim ------------- .. code-block:: vim " http://stackoverflow.com/questions/9104706/how-can-i-convert-spaces-to-tabs-in-vim-or-linux :set tabstop=2 " To match the sample file :set noexpandtab " Use tabs, not spaces :%retab! " Retabulate the whole file,替换tab为空格 map :%retab! :w " 映射一个命令 "https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwjF6JzH8aTRAhXiqVQKHUQBDcIQFggcMAA&url=http%3A%2F%2Fstackoverflow.com%2Fquestions%2F71323%2Fhow-to-replace-a-character-by-a-newline-in-vim&usg=AFQjCNGer9onNl_RExCUdE75ctTvVx8WGA&sig2=WrcRh9RFNvN6bUZoHpJvDg "vim替换成换行符使用\r不是\n " 多行加上引号 http://stackoverflow.com/questions/9055998/vim-add-tag-to-multiple-lines-with-surround-vim" :1,3norm yss" # Git 插件 Plugin 'tpope/vim-fugitive' # 在 vim 里执行 :Gblame 可以看到当前文件每行代码的提交人和日期,找人背锅或者咨询的神器 # 直接在 vim 里 diff 文件,比如打开了两个文件 :windo diffthis :diffoff! # 解决mac vim 中文输入法的问题 # https://www.jianshu.com/p/4d81b7e32bff # https://zhuanlan.zhihu.com/p/23939198 brew tap daipeihust/tap && brew install im-select # 终端下执行此命令安装 im-select # 然后 vim 配置加入这一行 (ABC 是默认输入法,直接输入 im-select 可以看到你的默认值) `autocmd InsertLeave * :silent !/usr/local/bin/im-select com.apple.keylayout.ABC` # 如果跳转到跳转之前的位置, https://vi.stackexchange.com/questions/2001/how-do-i-jump-to-the-location-of-my-last-edit # 使用场景:比如在当前函数里使用了logging,发现logging import,我会跳转到文件头去 import logging,编辑完后进入normal模式使用 `` 就可以跳转到之前编辑位置 `` which will bring you back to where the cursor was before you made your last jump. See :help `` for more information. # 如何编辑远程服务器文件, https://superuser.com/questions/403664/how-can-i-copy-and-paste-text-out-of-a-remote-vim-to-a-local-vim :e scp://user@host/relative/path/from/home.txt # 跳转 g # list all match tag # 跳转到上一个 insert 的位置,经常用在修改之后跳转到之前的编辑位置 https://vi.stackexchange.com/questions/2001/how-do-i-jump-to-the-location-of-my-last-edit `^ 或者 '^ # vim 替换不间断空格,illegal character U+00A0异常解决。https://www.jianshu.com/p/5f9992e5cd47 :%s/\%u00a0/ /g # set transparent,设置透明,如果iterm2 设置了背景图可以看到 :hi normal guibg=000000 # vim 去掉 ^M 字符(这个字符用 type CTRL-V, then CTRL-M. 打出来)。 # 或者 brew isntall dos2unix,然后 dos2unix filename :s/^M$// # vim 鼠标拖移窗口大小。设置鼠标支持即可。如果不生效:Iterm2->Profiles->Terminal->"Enable mouse reporting" 勾一下 # 参考:https://stackoverflow.com/questions/62582721/how-to-fix-restore-mouse-controls-in-tmux-on-iterm2 :set mouse=a # 如何全局替换多个文件的字符串。使用 far.vim 或者如果安装了 coc.nvim 可以使用 CocSearch 命令 :Far foo bar **/*.py # iterm2 下 set mouse=a 之后vim/neovim不生效,无法鼠标拖动窗口大小 Settings -> Profiles -> Terminal -> Enable mouse reporting * `《vim cheet sheet》 `_ vim-go/coc.nvim plugin Tips ----------------------------------------- .. code-block:: vim # 最近一直在开发机服务器上直接用 neovim+vim-go+coc.nvim 写 golang,具有完备开发功能(vim-go借助各种go工具实现) # https://github.com/fatih/vim-go # https://github.com/fatih/vim-go-tutorial # vim-go 官方教程,最好过一遍 let g:go_def_mode='godef' # 有时候 gopls 有问题可以用 godef 跳转,默认用 gopls # 如何生成 interface 接口定义 type S struct{} # cursor 放在 S 上执行 :GoImpl io.Reader # 跳转到接口的实现 https://github.com/fatih/vim-go/issues/820 :GoDef (或ctrl+]) 跳转到定义,但是如果是接口实现只能跳转到 interface 定义而非 struct 实现。 :GoCallees 从函数调用处跳转到接口的真正实现,而不是接口定义 (在方法调用点使用 -> struct 方法实现列表) :GoCallers 找到当前函数被调用的地点 (caller 主调, callee 被调) :GoImplements 获取一个接口方法的所有实现列表。(interface method -> implement method list) # 常用的方便命令(命令模式Tab补全), 参考 https://github.com/fatih/vim-go/blob/master/doc/vim-go.txt :GoFmt 格式化,你可以配置 vim-go 直接保存自动执行格式化或者直接执行 GoImports :GoRun, GoTest, GoTestFunc 运行代码和单测 :GoMetaLinter 执行 lint,可以配置 .gometalinter.json 忽略一些 lint 错误。https://github.com/PegasusWang/linux_config/blob/master/golang/gometalinter.json :GoRename 快速重构 :GoImpl 为 struct 生成接口函数定义(光标放到struct定义上使用)。如果一个 interface 有很多需要实现的函数,比较方便 :GoAddTags GoRemoveTags json 快速给 struct field 增加 json tag,支持 visual 模式多选。默认 tag 名是下划线命名 :GoKeyify 把无名称初始化的 struct literals 转成包含字段名的初始化方式 :GoIfErr 生成 if err 返回值(或者用 snippets) :GoChannelPeers 寻找可能的 channel 发送和接收点 :GoFillStruct 给一个 struct 填充默认值 # 甚至还可以让超过 120 行的代码自动折行,需要安装 https://github.com/segmentio/golines # golines -w -m 120 red_dot.go # 直接命令行格式化,gofmt 没有长行的折行功能 # 在 vim 中使用 golines let g:go_fmt_command = "golines" let g:go_fmt_options = { \ 'golines': '-m 120', \ } " 以下是 coc.nvim 官方示例定义的快捷键。用好这几个快捷键可以给开发带来极大便利 " 跳转到变量定义。normal 模式下在一个变量名上按一下 gd 即可跳转到定义位置,然后ctrl-o 可以快速返回原位置 nmap gd (coc-definition) " 跳转到值的类型定义,或者跳转到函数的返回值类型。在你想要快速查找一个类型的结构的时候非常有用 nmap gy (coc-type-definition) " 跳转到 interface 接口的对应实现。比如查看go里一个 interface 被哪些 struct 实现了。如果在 struct 名字上使用可以找到当前 struct 实现了哪些 interface nmap gi (coc-implementation) " 打开当前变量、函数等被引用的列表。比如看一个 函数 在哪些地方使用了 nmap gr (coc-references) 用markdown文件制作html ppt ------------------------------------------------------------- .. code-block:: python apt-add-repository ppa:brightbox/ruby-ng apt-get update apt-get install ruby2.2 gem install slideshow slideshow install deck.js sudo pip install https://github.com/joh/when-changed/archive/master.zip when-changed rest.md slideshow build rest.md -t deck.js # mac: brew install fswatch, http://stackoverflow.com/questions/1515730/is-there-a-command-like-watch-or-inotifywait-on-the-mac jfswatch -o ~/path/to/watch | xargs -n1 ~/script/to/run/when/files/change.sh fswatch -o ./*.py | xargs -n1 ./runtest.sh # 比如写单元测试的时候修改后就让测试执行 # 也可以使用下边的工具用 Jupyter 做 slideshow,最大的特点是直接在浏览器里敲代码交互演示 # Reveal.js - Jupyter/IPython Slideshow Extension, also known as live_reveal # https://github.com/damianavila/RISE # 更推荐使用 reveal-md reveal-md slides.md -w PPT 技巧 ------------------------------------------------------------- .. code-block:: shell # 如何粘贴代码到 PPT 里边: 转成 rtf。直接粘贴没有代码高亮,转成 rtf 格式就可以了 # https://superuser.com/questions/85948/how-can-i-embed-programming-source-code-in-powerpoint-slide-and-keep-code-highli # pip install Pygments pygmentize -f rtf code.py | pbcopy # 粘贴到 ppt 之后需要选择 “保留源格式”,这样代码才有高亮 Benchmark ------------------------------------------------------------- .. code-block:: shell sudo apt-get install apache2-utils ab -c 并发数量 -n 总数量 url Ffmpeg && youbute-dl ------------------------------------------------------------- .. code-block:: shell # brew install youtube-dl # https://askubuntu.com/questions/486297/how-to-select-video-quality-from-youtube-dl # http://www.cnblogs.com/faunjoe88/p/7810427.html # 下载视频,支持油管、b 站等 youtube-dl -F "http://www.youtube.com/watch?v=P9pzm5b6FFY" youtube-dl -f 22 "http://www.youtube.com/watch?v=P9pzm5b6FFY" youtube-dl -f bestvideo+bestaudio "http://www.youtube.com/watch?v=P9pzm5b6FFY" # 目前youtube-dl 貌似不更新了,用 yt-dlp 代替 python3 -m pip install --force-reinstall https://github.com/yt-dlp/yt-dlp/archive/master.tar.gz # 转换格式,比如 flv -> mp4 https://superuser.com/questions/624565/ffmpeg-convert-flv-to-mp4-without-losing-quality ffmpeg -i input.flv -codec copy output.mp4 # 截取视频 ffmpeg -i input.mp4 -ss 00:01:00 -to 00:02:00 -c copy output.mp4 # https://gist.github.com/PegasusWang/11b9203ffa699cd8f07e29559cc4d055 # 截图 ffmpeg -ss 00:10:00 -i "Apache Sqoop Tutorial.mp4" -y -f image2 -vframes 1 test.png # 提取音频mp3, https://stackoverflow.com/questions/9913032/ffmpeg-to-extract-audio-from-video ffmpeg -i sample.avi -q:a 0 -map a sample.mp3 # 连接视频 $ cat input.txt file '/path/to/file1' file '/path/to/file2' file '/path/to/file3' # 注意用 -safe 0 ffmpeg -f concat -safe 0 -i input.txt -c copy output.mp4 # youtube-dl 下载音频: https://askubuntu.com/questions/178481/how-to-download-an-mp3-track-from-a-youtube-video youtube-dl --extract-audio --audio-format mp3