Unix/Linux Quick Card
cd
[切换工作路径]
  • cd -
  • cd ~/test

which
[查询命令文件所在路径]
which java
whereis
[查询文件所在路径]
whereis git
chmod
[修改文件或目录权限]
  • chmod 755 file1
  • chmod -R +x folder
  • chmod +x file1
mkdir
[创建目录]
  • mkdir folder1
  • [ ! -d folder ] && mkdir folder
  • mkdir -p /local/tmp/test
mv / cp
[移动及重命名/复制]
  • mv file /destination/
  • mv filename newname
  • cp file1 file2
rm
[删除文件]
  • rm -f file
  • rm -r folder
echo
[输出]
  • echo $JAVA_HOME
  • echo 123 > file.txt
head / tail
[显示最前/后10行]
  • ls lrt | head -5
  • tail -f file.log
less / more
[分页显示数据]
  • less file
  • more file
touch
[创建或更新文件修改时间]
touch filename
hostname / uname
[显示计算机名/操作系统名称]
  • hostname
  • uname -a
su / sudo
[切换到超级用户或另一用户/用超级用户权限执行]
  • sudo rm -fr /local/folder
  • su - username
reboot / shutdown
[重启/关闭计算机]
  • shutdown -g04:30 -f"message"
  • reboot
id / users / who / whoami / w
[显示各类信息]
  • id username
  • users
  • who
  • whoami
uptime
[系统上线时间及负载]
uptime
kill
[发送信号给进程]
  • kill -l
  • kill -9 1234
curl / wget
[访问网站/下载文件]
  • curl http://www.x.com
  • wget http://www.x.com/1.txt
  • wget -i list.txt
df
[查剩余空间]
df -h ./
zip / unzip
[压缩/解压]
  • zip -m log.zip *.log
  • zip -mr t.zip folder
  • unzip -d ./folder t.zip
pwd
[Print working directory输出当前所在目录]
  • pwd
  • echo $PWD
clear
[清屏]
clear
date
[日期输出]
  • date +%Y%m%d
  • date -d "last week Monday"
  • date --date='TZ="Asia/Shanghai" last Friday'
at
[定时执行程序]
  • at 4am -f shell.sh
  • at 3pm + 2 days -f shell.sh
  • atq
  • at now +5 minutes
zip / unzip
[压缩/解压]
  • zip -m log.zip *.log
  • zip -mr t.zip folder
  • unzip -d ./folder t.zip
md5sum
[md5编码]
  • md5sum filename
dos2unix
[EOL格式转换,windows转unix格式]
dos2unix filename
chown
[修改文件所有人]
  • chown -R newuser:newgroup dir_name
cut
[从每行截取]
  • echo 'a#b#c' | cut -d# -f 2
scp
[远程复制]
  • scp local_file remote_username@remote_ip:/local/remote_folder/remote_file
  • *免密码:
  • ssh-keygen
  • ssh-copy-id username@remote_host
Unix/Linux commands
Command
Example
ls
  • -l long 长格式显示
  • -r reverse 反序显示
  • -h human readable 大小带单位
  • -a all 显示隐藏文件 | -A 排除当前(.)及上层(..)显示
  • -t time 按创建时间先后排序
  • ls -ltra 由旧到新已长格式显示当前路径所有文件
  • ls -d -1 $PWD/* 显示当前文件夹内所有文件完整路径,排除文件夹
  • ls -1 /home/user/DB*/bin | xargs -n 1 cp -v test.ksh xargs -n 1表对前面命令分别执行n次操作, cp -v 显示复制进度,整体及将test.ksh复制到符合前面命令的路径中
cat [catenate]
  • -n number 显示行数编号
  • -b number-nonblank 同n,但空行不编号
  • -s squeeze-blank 同n,连续空行只显示一次
  • -v show-nonprinting
  • -1 数字1,每行只显示一条结果
  • cat file1 file2 > file3 将file1+file2内容按顺序合并至file3
  • cat file1 >> file1 报源文件与输出文件相同错误!正确可用 cat file1|tee -a file1 读文件并插入到源文件后
  • cat -n file.txt nl file.txt 等同命令,显示行号输出文件内容
sort
  • sort [-option] [-o output.file] [-t separator] [-k field 1[,field 2]]
  • -b 忽略每行前的空格
  • -d 排序时,处理字母数字空格,忽略其他字符
  • -n 依照数值大小排序
  • -u 唯一,结果去重
  • -o file.txt 输出排序结果到文件
  • -r 默认升序,该参数实现反向排序
  • -t 分隔符
  • -k field1,field2 按列排序
  • sort -n -r test.txt -k 2 按数字反序排序第二列
  • sort -u test.txt -k 3 根据第三列排序,去除重复行
alias
  • alias shortcmd='cmd1;cmd2;cmd3'
  • alias 列出当前所有别名命令
  • alias ll='ls -ltr color=auto' 创建ll命令,已代替后面长命令
  • alias cpy='scp ~/test.sh user@machine2:~/test/;rm abc.txt' 创建短命令执行多个命令,命令间用";"隔开
seq
  • seq [option] [min] [step] max
  • -f | --formart=格式 使用printf样式的浮点格式
  • -s | --separator=字符串 使用指定分隔符,默认转行符
  • seq -s '|' 4 1|2|3|4
  • seq 1 3 8 1 3 7
  • seq 1 5 echo {1..5}
  • seq 1 100 | xargs -I{} echo {} > t.txt 输出一百行到文件
sed
  • sed [-hnV][-e{script}][-f{script file}][file]
  • 参数:
  • -n | --quiet | --silent 只显示匹配处理的行,否则默认输出全部
  • -e[script] | --expression=[script]
  • -i 直接修改文件
  • 动作:
  • a 新增,接字符串,在目前一行的下一行插入
  • c 取代,接字符串,取代n1,n2之间的行
  • d 删除,不接任何东东
  • i 插入,接字符串,在目前一行的上一行插入
  • p 打印,将选择的数据输出,通常与-n参数一起用
  • s 取代,通常搭配正则,如1,20s/old/new/g
  • sed -i "s/old_word/new_string/g" file.txt 查找替换文件内容,"/"可用任意其他字符代替
  • nl file.txt | sed '3,$d' 行号指定一个处理某行,指定两个处理某段,$表示末尾,d为删除动作,即删除第三行至末尾,非处理文件而只是显示,等同head -2 file.txt | nl
  • cat file.txt | sed -n '17,25p' 显示文件的第17至25行
  • sed -i '$a test' file.txt echo "test" >> file.txt 等同命令,在末尾插入字符串
  • echo "/home/user/file.txt" | sed -i 's#/#@#2' 只替换第二个匹配的:/home@user/file.txt
  • echo 123456789 | sed 's#3\(.*\)6#a\1a#' \1表示前面括号匹配出的内容
  • sed -i 's/^$/d' file.txt 删除文件中的空白行
  • sed -e 's/[0-9]/newcontent/g' -e '3a insert line' file.txt 查找替换file.txt中的数字,并在第三行插入新行
awk
  • awk [option] 'condition{action}' [file]
  • 参数:
  • -F | --field-separator 分隔符
  • -f | --file 脚本文件
  • -v var='value' 自定义变量
  • 内置变量:
  • NR 行号,已经读出的记录数
  • FS 分隔符,默认空格或tab
  • NF 一条记录的字段的数目
  • OFS 输出字段分隔符,默认与输入字段一致
  • ORS 输出记录分隔符,默认换行符
  • RS 记录分隔符,默认换行符
  • 格式化输出 - %[标识][长度][精度]转换符 :
  • 标识:- 左对齐 | 空格 在正数前加空格 | + 显示正数负数符号 | 0 数字前补零
  • 转换符: c ASCII字符 | d/i 十进制整数 | f 浮点数 | s 字符串 | u/o/x/X 十进制/八进制/十六进制小x/大X
  • 精度含义: %d,$i,%o,%u,%x,%X 最少数字位数,小于时前面补0 | %f 保留小数位数 | %s 字符位数
  • 特殊表达式:
  • BEGIN 扫描前执行,通常显示变量和初始化
  • END 扫描结束执行官,输出最终结果
  • echo 'abc 30.45542 123 -111' | awk '{printf "%-8s %.2f %+2d %+5d \n",$1,$2,$3,$4}' abc 30.46 +123 -111, 字符串长度正数则左侧补全,负数则右侧补全,浮点数四舍五入保留精度
  • ls -l *.log | awk '{sum+=$5} END {print sum}' 计算并输出当前文件夹中txt文件总大小
  • awk 'length>100' file.log 找出lfile.log中长度大于100的行
  • seq 9 | sed 'H;g' | awk -v RS='' '{for(i=1;i<=NF;i++)printf("%dx%d=%d%s", i, NR, i*NR, i==NR?"\n":"\t")}' 输出九九乘法表
  • awk -v var='' 'BEGIN{var=rand();print var} 自定义变量,内置函数rand()得到0~1之间的随机数
  • awk -F '|' '{a[$12]++} END{for(i in a) print i ":" a[i]}' File_name*.csv|sort -n -k 1 统计多文件中某列不重复值出现次数,按升序排列,a[$12]第十二列循环一次+1,END循环完输出,
  • sed -n '3p' file.txt | awk '{print $4}' 获取第三行第四列
find
  • find path -option [-exec -ok command] {} \;
  • -amin n 过去n分钟内被读过
  • -anewer file 比file更晚被读取的文件
  • -atime n 在过去n天内被读取过
  • -cmin n 近n分钟内被修改过的
  • -ctime n 近n天内被需改过的,负数则表n天以前
  • -cnewer file 比file更新的文件
  • -empty 空文件
  • -name name/ -iname name 文件名符合name的,可通配符,iname忽略大小写
  • -size n 文件大小,b字节,c字符数,k千字节(kb)
  • -type d 文件类型,d文件夹,f文件,l链接文件
  • -maxdepth level 查找深度,1表至查当前路径不进入子目录
  • *n 第n天, +n n天前不含第n天, -n n天以内
  • find . -type f -name "*.log" -ctime +90 -exec ls -lrt {} \; 找出当前文件夹中修改时间为90天以前的.log文件,以长格式输出结果
  • find -type f -empty -exec -ok rm {} \; 找出空文件并确认删除
  • find -name 'abc.txt' -or -name '123.txt' 多条件查询
du
  • du [-option][-X file][--exclude={dir/file}][--max-depth][dir/file]
  • -a | -all 显示目录中个别文件的大小
  • -h | --human-readable大小显示单位
  • -c | --total 出显示个别大小外,同时显示总大小
  • -s 只显示总大小
  • --exclude={dir or file} 排除目录或文件不统计
  • -d | --max-depth=N 指定层级N,超过时忽略
  • du -sh /home/tmp 输出指定文件夹占用大小
  • du -a | sort -nr | head -20 列出前20大文件
  • du -s * | sort -nr | head 列出前10大目录
tr
  • tr [-option] [set 1] [set 2]
  • 参数:
  • -c | --complement 反选字符,符合set 1的不处理,不符合才转换
  • -d | --delete 删除指令字符
  • -s | --squeeze-repeats 缩减连续重复的字符成指定单个字符
  • -t | --truncate-set1 削减set1的范围,使其与set2长度相同
  • 字符集合:
  • [:alnum:] 所有字母和数字
  • [:alpha:] 所有字母
  • [:blank:] 所有空格
  • [:digit:] 所有数字
  • [:lower:] 所有小写字母
  • [:upper:] 所有大写字母
  • CHAR1-CHAR2 指定范围,按ASCII码从小到大
  • echo 'abcdefghijklmn' |tr a-f 1 111111ghijklmn
  • echo 'abCdE' |tr [:lower:] [:upper:] ABCDE, 同tr a-z A-Z
tar
  • -A 新增文件到已存在的备份文件
  • -c 建立新备份文件
  • -f filename指定备份文件
  • -v 显示执行过程
  • -z 通过gzip指令处理备份文件
  • --delete 从备份文件中删除指定文件
  • -t 列出备份文件的内容
  • -x 还原文件
  • -k | --keep-old-files 解压时不覆盖已有文件
  • tar -czvf test.tar.gz testfolder 新增备份文件
  • tar -tzvf test.tar.gz 查看备份文件内容
  • tar -xzvfk test.tar.gz 解压文件,不覆盖已存在文件
ps
  • -A | -e 显示所有进程
  • -f 完全格式显示
  • -w 加宽格式显示
  • -o format 自定义格式显示
  • -u username 显示指定用户进程
  • ps -ef | grep java 查找java相关进程
  • ps axjf 树形打印进程
  • ps -eo pid,tid,class,ruiud,tty,stat,wchan:14,comm 定义显示的列
  • ps aux | head -1;ps aux |grep -v PID |sort -rn -k +4 | head -20 显示前二十个内存占用最高的进程
  • ps -eLf | grep java | wc -l 监控java线程数
  • *查CPU占用率和内存占用率,可以使用aux,查进程父进程ID和完整命令用ef
netstat
  • -a 显示所有,默认不显示listen相关
  • -l 仅列出有在listen的服务状态
  • -t 仅显示tcp相关
  • -u 仅显示udp相关
  • -p 显示建立相关连接的程序名
  • -s 按各协议进行统计
  • -n 直接使用IP地址,不用域名服务器
  • -i 显示网卡列表
  • netstat -n | grep tcp | grep 80 | wc -l 监控网络客户连接数
  • netstat -au 列出所有udp端口连接
  • netstat -l 只显示监听端口
top
  • -d 更新速度,单位秒,默认1秒
  • -i 不显示闲置(idle)或无用(zombie)进程
  • -S 累积模式,累积已完成或消失的子进程
  • -n 更新次数,完成后退出top
  • 第一行top-:系统时间,上线时间,登录用户数,负载情况(1min,5mins,15mins) - 负载数除以逻辑CPU数大于5时说明超负荷运转
  • 第二行Tasks:任务进程总数,运行中进程,休眠中进程,停止进程数,僵尸状态进程数
  • 第三行CPUs:用户空间(应用程序)占用比,内核(系统和驱动程序)占用比,改变过优先级的进程占用比,空闲cpu百分比,IO等待占用比,硬中断(hardware IRQ)占用比,软中断(Software interrupts)占用比
  • 第四行MiB Mem:总物理内存,使用中的内存,空间内存,缓存的内存
  • 第五行MiB Swap:交换区总量,使用中的交换区总量,空闲交换区总量,缓冲的交换区总量 (系统开始频繁使用交换区内存,说明内存开始不足)
  • 可用内存计算公式:free mem + buffers + swap cached free -h | sed -n '2p'|awk '{print $4}'
git
  • git init 初始化仓库
  • git clone [-b develop] https://github.com/userid/projectid.git 下载项目
  • git add filename.php 添加文件到暂存区
  • git commit -m 'description message' 提交暂存区文件,附带简介信息
  • git fetch [alias]; git merge [alias]/[branch] 从远程获取代码库,然后合并到当前分支
  • git diff 对比暂存区与工作区的文件差异
  • git pull 同git fetch;git merge FETCH_HEAD,从远程更新本地文件并合并
  • git push 上传代码并合并
  • git branch branch_name git branch查看已有分支,加第二参数则创建分支branch_name
  • git checkout master 切换分支
  • git branch -d branch_name 删除分支
  • git merge 主分支中执行,合并分支
  • git reset --hard HEAD^^ 回滚当前版本的上上个版本,HEAD当前,^上一个,^^上上个版本,.或具体版本ID前几位
  • git status 查看本地工作区和暂存区的状态
  • git log 查看操作日志
  • 远程仓库 git pull 工作区git add 暂存区git commit 本地仓库 git push 远程仓库
svn
  • svn checkout https://svn-repostory.com/test 下载项目至本地仓库
  • svn diff 比较本地文件与远程仓库差异
  • svn update 同svn up,更新本地仓库文件
  • svn status 查本地文件状态,是否已提交更新
  • svn add file 添加待commit文件
  • svn commit -m 'descript message' 提交代码更新至远程仓库,成功版本后增加1
  • svn revert file 回滚本地文件,或svn revert -R folder 回滚整个项目文件
  • svn copy master branches/my_branch 创建分支,即复制主仓库
  • svn merge ../branches/my_branch 合并分支到主分支,commit提交改动
rpm/yum
  • [Redhat,Centos,Federo| yum自动解决依赖]
  • -a 查询所有套件
  • -q 查询模式,遇到问题时先询问用户
  • -h 套件安装时列出标记
  • -v 显示指令执行过程
  • -i 显示套件相关信息
  • -e 删除套件
  • --nodeps 不检验依赖关系
  • --force 强制安装
  • rpm -hvi dos2unix-7.4.2-4.el9.x86_64 安装包
  • rpm -qa | grep dos2unix rpm -qa dos2unix 查看包
  • rpm -e dos2unix-7.4.2-4.el9.x86_64 删除包,包名不能包含.rpm
  • ls -lrt /etc/yum.repos.d/*.repo yum软件源设置文件
apt-get
  • [Debian,Ubuntu]
  • -y 确认安装
  • -q 静默安装
  • remove 删除包,但保留配置
  • autoremove 删除包并删除依赖(据说容易多删除,尤其非经由apt安装的包)
  • purge 删除包及配置
  • update 更新包来源,检测版本有无更新
  • upgrade 升级包
  • source list: /etc/apt/sources.list
  • dpkg-query -l 列出已安装包
  • apt-cache search nginx 搜索包
  • sudo apt-get install -y apache 无需确认安装Apache
  • sudo apt-get purge apache 卸载软件
  • sudo apt-get update; sudo apt-get upgrade 更新软件
keytool
  • -alias 别名
  • -keystore 密钥库
  • -keyalg 默认DSA,其他算法如RSA
  • -validity 证书有效天数
  • -keysize 密钥长度
  • -list 列出密钥库中的信息
  • -delete 删除密钥库中的某条
  • -storepass 密钥库密码
  • -import 导入证书到密钥库
  • keytool -genkeypair -alias servername -keypass keypwd -storepass storepwd -dname “C=CN,ST=SD,L=QD,O=Ognization,OU=UAT,CN=canwong.com” -keyalg RSA -keysize 2048 -validity 365 -keystore /tmp/certs/trust.jks 生成证书
  • keytool -list -keystore store.jks -storepass password 列出store.jks中的信息
  • keytool -delete -alias aliasname -keystore store.jks -storepass password 删除store.jks中的aliasname
  • keytool -import -alias aname -keystore store.jks -file pub.pem -storepass password 证书导入到密钥库中
Trouble Shoot Network and disk & file system issue
  • dstat -t yum install dstat如果命令不存在,默认每秒统计网络总发送/接受,IO总写入/读取等
  • netstat -tnlaup 查哪个进程用了哪个端口
  • lsof -i -P 类似同上
  • ngrep -d 抓包工具,安装:yum install libpcap
  • tcpdump 同上,抓包分析,类似wireshark
  • opensnoop 实时查看正被打开的文件,安装:yum install bcc-tools && export PATH=$PATH;/usr/share/bcc/tools
  • echo net.ipv4.ip_nonlocal_bind=1 >> /etc/sysctl.conf 负载均衡如haproxy时开启
curl
  • -H header请求头
  • -XGET | -XPOST | -XPUT | -XDELETE 请求方式
  • -D data请求数据
  • -I 响应头
  • -O | -o 小写指定本地重命名下载文件
  • --limit-rate 100k,无单位默认字节限制速度
  • -v 显示连接过程
  • -L 跟随重定向
  • --proxy 代理访问
  • curl www.baidu.com
  • curl -xpost -H 'Content-Type:application/json' -d '{"name":"Ken"}'
Script Comparasion
Batch
定义变量&数学计算
set var=value
set /a var=123 ::digit only
echo %var%

set /a sum=123+456 ::加/a数学计算
                        

字符截取
set yyyy=%date:~0,4% ::从开头截取4个长度
set str=abcdefghijklmn
echo %str:~4,2% ::ef 第4字符后截取2个长度
echo %str:~-3,2% ::ij 倒数第三字符截取2个长度
echo %str:~-4,-3% ::h 倒数第四开始截取到倒数第三
                        

判断&循环
if "%a%"=="%b%" (
    echo %a%
) else (
    echo %b%
    if conditon (
        action
    )
)

if 1 GTR 2 (echo true) else (echo false)
if defined var (echo true) else (echo false)
if ERRORLEVEL 1 ECHO can not find the file
if ERRORLEVEL 0 ECHO success

REM 循环
for %%x in (*.txt) do echo "%%x"
for  /F "tokens=2,3* delims=|" %%a in (file.txt) do (
    echo %%a
    echo %%b
)
REM 文件循环,以|分割取第二列,第三列及后续列

forfiles /S /P D:\dir /M *.log /D -60 /C "cmd /c echo @file && del @path"
                        

方法定义&调用(lable)
setlocal enabledelayedexpansion

call :function1 param1 param2
goto :eof

:function1
echo %1
echo %2
goto :eof
                        

数据库操作
sqlcmd -S db_hostname -d db_name -U db_user -P db_password -i script.sql -o output.log
House Keep Sample
@echo off

set folderList=D:\app\log
set folderList=%folderList%;D:\app\processed
set folderList=%folderList%;D:\app\tmp

echo %folderList%

for %%x in (%folderList%) do (
    forfiles /S /P %%x /M *.log /D -90 /C "cmd /c del @path"
)
                            

FTP Download sample
@echo off

set today=%date:~0,4%%date:~5,2%%date:~8,2%

date /t | findstr /i "周一" && call :Monday || call :Weekday

echo lcd D:/download > tmp.ftp
echo cd /home/user/test >> tmp.ftp
echo mget FileType_*_%today%.txt >> tmp.ftp
echo mget AnotherFile_*_%ytd%.txt >> tmp.ftp

C:\putty\psftp.exe username@server -pw password -b"tmp.ftp" -bc

goto :eof

:Monday
echo called monday
for /f %%x in ('PowerShell "(get-date).AddDays(-3)|get-date -format \"yyyyMMdd\""') do (set ytd=%%x)
goto :eof

:Weekday
echo called weekday
for /f %%x in ('PowerShell "(get-date).AddDays(-1)|get-date -format \"yyyyMMdd\""') do (set ytd=%%x)
:goto :eof
                            

batch | exe注册为服务
  • Option1: sc create ServiceName binPath= "D:\test\service.bat" start= auto
  • Option2: instsrv.exe ServiceName D:\tmp\srvany.exe
    • 修改regdit: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName
    • 新建Parameter项目
    • 新建Application字符串值: D:\test\service.bat
    • 新建AppDirectory字符串值: D:\test\
    • 新建AppParameters字符串值: 无需参数设空值

获取md5值并赋值给变量
@echo off
setlocal enabledelayedexpansion

pushd %~dp0

set /a count=1

for /F "skip=1" %%x in ('certutil -hashfile BZ1802271950450159.jpg MD5') do (
    if !count! equ 1 set MD5=%%x
    set /a count+=1
)

echo %MD5%
echo %MD5: =%
                            
Shell
定义变量&数学计算
var=value
${var:-default} #变量未定义或未赋值则返回后面的默认值
var=$([ "$a" == 1 ] && echo 'true' || echo 'false') 
#三元赋值,&&优先级高于||
echo ${var}

expr 1 + 3
((sum=10+15)) #直接赋值变量,不输出结果
echo $((4+5))
let "c=a*b"
                        

字符截取
var=1234567890987654321
echo ${var#*7} #890... #从左边开始删除第一匹配的左边,保留右
echo ${var##*7} #6543...  ##从左边开始删除最后一个匹配的左边,保留右
echo ${var%7*} #...098 %从右开始删除第一个及右侧内容
echo ${var%%7*} # 123456... %%从右开始删除最后一个及右侧
echo ${var:0:5} #从最左侧0位置开始截取5个长度
echo ${var:13} #654321 从左侧第N个开始截取到末尾
echo ${var:0-5:3} #543 从右侧第5个开始截取3个长度
echo ${var:0-5} #54321 从右侧第5个开始截取到末尾
                        

判断&循环
if [ $a > 5 ] && [ $b > 5 -o $c -eq 0 ] ; then
    echo $a
elif [ $c > 10 ]; then
    echo $c
else
    echo $b
fi

#[ -f file ] 文件file存在为真
#[ -d dir ] 目录dir存在为真
#[ -s file ] 文件file存在且大小不为0时为真
#[ -w file ] 文件file存在且可写为真
#[ file1 -nt file2 ] file1修改时间更新时为真
#[ -z string ] 字符串string长度0时为真
#[ -n string ] 字符串string长度非0时为真
#[ str1 != str2 ] 字符串不同时为真

case $var in
'value 1')
    do something
    ;;
'value 2')
    do something
    ;;
*)
    do something
    ;;
esac

for x in {1..10}
do
    case $x in 
    5)
        echo "skip"
        continue
        ;;
    8)
        echo "exiting loop"
        break
        ;;
    *)
        echo $x
        ;;
    esac
done

for f in $(ls /var)
do
    [ -d $f ] && du -sh $f
done

while ((x<=10))
do
    let sum+=1
    let x++
done
                        

方法定义&调用
function sum()
{
    echo "input first number"
    read a
    echo "input second number"
    read b
    let "result=$a+$b"
    echo $result
}

sum

anotherFun()
{
    echo $1
    echo $2
}

anotherFun 1stParam 2ndParam

#参数
# $# 参数个数
# $* 作为字符串显示全部参数
# $@ 同上但显示时带引号
# $$ 脚本运行的当前进程ID
# $? 最后命令的状态,0表成功,类似batch ERRORLEVEL
                        

数据库操作
outvar=$(sqlplus -s db_user/db_pass@db_hostname << EOF
SET HEAD OFF FEEDBACK ON
select * from tablename;
${sqlvar}
@/dir/sqlfile.sql
EOF)

#feedback默认少于6条记录时不显示, show feed | set feed 3
                        
Python3
定义变量&数学计算
var=value
var = a if a > 5 else b 
#三元赋值[on true] if [expression] else [on false]
print(var)

sum = 4 + 5
print(sum-3)
                        

字符截取(切片)
var = '1234567890'
print(var[2:5]) #345 从第3位截取到第6位
print(var[8:]) #90 从第9位截取到末尾
print(var[4:-3]) #567 从第5位截取到倒数第4位
print(var[-4:]) #7890 截取倒数4个长度
print(var[-3]) #8 获取倒数第3个字符
                        

判断&循环
if (num >= 0 and num <= 5) or (num <=10 and num >= 7):
    print('it is 5')
elif num == 11:
    print('it is 11')
elif num < 15:
    print('it is less than 15')
else:
    print('this is else')

if ( var == 10 ): print('var is 10')

numbers = [12,34,51,8,23,4,7]
even = []
odd = []
while len(numbers) > 0 :
    number = numbers.pop()
    if (number % 2 == 0):
        even.append(number)
    else
        odd.append(number)

for letter in 'python'
    if letter == 'h'
        break
                        

方法定义&调用
def sum(n1,n2):
    result = n1 + n2
    return result
                        
print(sum(4,5))                        
                        

数据库操作
#-------第三方程序---------
os.chdir(db_bin_path)
isql_command = ['./isql',
    '-H',db_host,
    '-S',db_server,
    '-U',db_user,
    '-P',db_pass,
    '-D',db_name,
    '-i',sql_file,
    '-o',out_file,
    '-w',10000
]

stats = subprocess.call(isql_command)

#----------内置库连接sqlite-----
import sqlite3

conn = sqlite3.connect('test.db')

newtable_sql = '''
create table user(
    name text not null,
    sex integer not null,
    id integer not null primary key autoincrement);
'''
insert_sql = 'insert into user (name,sex,id) values ("%s",%d,%d)'%("Ken",1,1)

with conn:
    conn.execute(newtable_sql)
    conn.execute(insert_sql)
    records = conn.execute('select * from user')
    for record in records:
        print(record)

#------连接MySQL---------
pip install pymysql

import pymysql
                        

Windows中注册为服务

pip install pyinstaller

pyinstaller -F service.py 得到dist\service.exe文件,其余临时文件可删除

Python Notes
数据类型
  • 数字Number: int1,float2 = 123,3.1415926
  • 字符串string: str1,str2 = '123','randome string'
  • 列表list: list1 = [1,'python',2343,'word']
  • 元组Turple: tup1 = ('string','version 123', 12345,"string2")
  • 字典Dictionary: dict1 = {'var1':123,'var2':'123','var3':'string'}
  • 集合Set: set1 = set();set2 = {'apple','orange',111,34,'random'}

数字类内置函数
  • 绝对值: abs(-100)
  • 返回最大值/最小值: max(12,32,543) | min(12,5,24)
  • 四舍五入: round(3.1415926,4)*精度可选
  • 比较大小[operator]: operator.lt(num1,num2) *le,eq,ne,ge,gt
  • 返回[0,1]随机数[random]: random.random()
  • 随机生成实数[random]: int(random.uniform(100,200))
  • 从序列元素挑随机整数[random]: random.choice(range(10))
  • 计算平方根[math]: math.sqrt(16)
  • 计算次方x**y[math]: math.pow(2,4)
字符串内置函数
  • 查找字符串返回索引值,找不到返回-1: str.find('a',2,10)
  • 判断字符串非空且全为数字或字母: str.isalnum()
  • 判断字符串非空且全为字母: str.isalpha()
  • 判断字符串值包含数字: str.isdigit()
  • 指定分隔符连接字符串元组元素: seq = ('abc','123','efg'); '|'.join(seq)
  • 返回字符串长度: len(str)
  • 替换字符串: str.replace('old','new')
  • 删除两端空格或指定字符: strip(str)
  • 默认按空格分割字符串: url.split('/')[-1]

列表&元组内置函数
  • 列表/元组元素个数: len(var)
  • 返回最大值/最小值: max,min = max(var),min(var)
  • 元组转换成列表: list(seq)
  • 末尾添加对象: list_var.append('f')
  • 移除元素,默认最后一个: list_var.pop()
  • 对元素排序: list_var.reverse()
字典内置函数
  • 清除字典: dict.clear()
  • 获取指定键的值,不存在则返回默认: dict.get('name','Ken')
  • 获取指定键的值,不存在则添加并设置默认值: dict.setdefault('name','Ken')
  • 返回字典所有键的视图对象: dict.keys()
  • 删除字典最后一对键值对: dict.popitem()
  • 将另一字典更新到当前字典中: dict.update(dict2)
  • 删除指定键的值,返回被删除的值,键不存在时返回默认值: dict.pop('name','no name')
  • 判断键存在与否(key in dict): 'name' in dict

集合内置函数
  • 集合元素个数: len(set2)
  • 默认去重: print(set('aaaaaa')) * 输出{'a'}
  • 判断元素存在与否(key in set): 'apple' in set2
  • 交集intersection(): a & b, 并集union(): a | b, 差集symmetric_difference(): a ^ b, 补集: a - b
  • 添加元素,已存在则不操作: set1.add('abc') | set1.update('abc')
  • 移除指定元素,不存在不报错: set1.discard('a')
  • 移除随机元素: set1.pop()
Python 2 VS Python 3

类型
Python 2.X
Python 3.X
Unicode编码
ASCII编码,添加头部变更:# -*- coding: utf-8 -*-
默认utf-8
输出
语句print a,b 或 函数print(a,b)
只保留函数print(a,b)
除法
整数相除忽略小数
整数浮点数相除均得浮点数
不等于
<> 或 !=
只保留!=写法
长整数
区分int和long
废除long,统一为int
has_key()
判断key是否存在于字典
废除,改用key in dict
xrange()
range()返回列表,xrange()返回迭代器
废除,range()返回迭代器
raw_input()
input()接受整数,raw_input()接受字符串
废除,统一input()接受字符串
模块整合
URL及DBM相关模块多个
整合至urllib(urllib.request,urllib.error...),dbm(dbm.ndbm,dbm.gnu...)

随心记
  • ~表示反转, ~x <=>-(x+1) | ~True <=> false | list[~3] <=> list[-(3+1)]
  • 简化判断输出 print('correct' if (1!=0) else 'wrong')
  • 切片list[start:end:step] | 插入切片list[2:1]=["F"] | 删除切片del L[2:2]

简易爬虫
import requests
import time
from lxml import etree

# 爬取内页图片地址并保存
def get_pics(url):
    inner_page = requests.get(url,timeout = 30).text
    inner_html = etree.HTML(inner_page)
    pic_src = inner_html.xpath('//div[@class="entry-summary"]/p/a/@href')
    for x in pic_src:
        print(x)
        if x[-4::] == '.jpg':
            print('yes')
            filename = x.split('/')[-1]
            pic = requests.get(x,timeout = 15)
            with open('D:\\python\\test\\pic\\{}'.format(filename),'wb') as f:
                f.write(pic.content)
                f.close()

# 爬取网站文章进行循环
webindex = requests.get('http://xxxxxx.com/',timeout = 30).text
html = etree.HTML(webindex)
articel_url = html.xpath('//div[contains(@class,"post")]/h2/a/@href')
for i in articel_url:
    get_pics(i)
    time.sleep(2)                              
                            
import OS
  • os.chdir(path) 切换工作目录
  • os.listdir(path) 列出当前或指定目录下所有文件或目录的列表
  • os.remove(path) 删除文件 | os.removedirs(path) 递归删除目录 | os.rmdir(path) 删除空文件
  • os.rename(old,new) 重命名文件或目录 | os.renames(old,new) 递归地进行重命名
  • os.path.abspath(path) 返回绝对路径 | os.path.basename(path) 返回文件名 | os.path.dirname(path) 返回文件路径
  • os.path.getatime(path) 最近访问时间 | os.path.getmtime(path) 最近修改时间 | os.path.getgctime(path) 创建时间 用time.ctime()转换为可读时间
  • os.isfile(path) 判断是否为文件 | os.path.isdir(path) 判断是否为目录
  • os.path.join(os.path.dirname(path) + os.sep + os.path.basename(path)) 合并为路径
  • os.path.samefile(path1,path2) 对比文件或目录是否相同
  • os.path.split(path) 将路径分割为目录名和文件名,返回一个元组 | os.path.splitdrive(path) 类似,一般用于win系统返回驱动器名和路径

import configparser
config = configparser.ConfigParser()

config.add_section('mysql_conn')
config.set('mysql_conn','host','localhost')
config.set('mysql_conn','user','dbuser')
config.set('mysql_conn','port','1234')
config.set('mysql_conn','password','dbpass')
config.set('mysql_conn','database','testdb')

config.add_section('user_info')
config.set('user_info','admin','KenWong')
config.set('user_info','password','abc123')

with open('config.ini','w') as f:
    config.write(f)

read_config = configparser.ConfigParser()
read_config.read('config.ini')
dbinfo = read_config['mysql_conn']
userinfo = read_config['user_info']
print(dbinfo['host'])
print(userinfo['admin'])
                                        
Sending Request
import requests
import threading

url = 'http://xxxxx/xxxxx.php'

data = {
    'data1':'value1',
    'data2':'value2',
    'data3':'value3'
}

def do_request():
    while True:
        respone = requests.post(url,data=data).text
        print(respone)

threads = []

for i in range(50):
    t = threading.Thread(target=do_request)
    t.daemon = True
    threads.append(t)

for i in range(50):
    threads[i].start()

for i in range(50):
    threads[i].join()
                                        

IBM text to speech
from ibm_watson import TextToSpeechV1
from ibm_watson import ApiException
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

authenticator = IAMAuthenticator('KdI4XU0xoRIuQgGfeIArzhutuH73gmfO3WKZxz8_hpCy')
text_to_speech = TextToSpeechV1(
    authenticator=authenticator
)
text_to_speech.set_service_url('https://api.jp-tok.text-to-speech.watson.cloud.ibm.com')
text_to_speech.set_disable_ssl_verification(True)
voice = 'zh-CN_LiNaVoice'
audiotype = 'audio/wav'
extend_name = '.wav'
# audiotype = 'audio/wav;rate=22050'

def downAudio(filename,content_text):
    filename = '.\\voices\\'+filename+extend_name
    try:
        with open(filename, 'wb') as audio_file:
            audio_file.write(
                text_to_speech.synthesize(
                    content_text,
                    voice=voice,
                    accept=audiotype
                ).get_result().content)
    except ApiException as ex:  
        print("Method failed with status code " + str(ex.code) + ": " + ex.message)


with open('words.txt','r',encoding='utf-8') as f:
    for line in f:
        para = line.split(':',1)
        downAudio(para[0],para[1])
                                        
Docker Notes
命令&操作
查看版本/信息
docker version
docker info
命令帮助
docker [action] --help
设置开机启动
systemctl start docker
systemctl enable docker
查看本地已有镜像
docker images
删除本地镜像
docker rmi imagename:tagname
查找镜像
docker search nginx
下载镜像到本地
docker pull mysql
创建自定义镜像[编写Dockerfile]
docker build -t imagename:tagname -f Dockerfile .
下载/运行docker容器
docker run -d -p 8080:80 --name nginx-server --restart=on-failure:5 -v /opt/nginx-server:/usr/share/nginx/html:ro -v /opt/nginx-config/nginx.conf:/etc/nginx/nginx.conf:ro nginx:latest
  • -d 后台运行
  • -p 端口映射,,本地端口:容器端口,大写-P不写端口则自动分配
  • --name 自定服务名
  • --net=netmode 网络模式netmode可选值:bridge(默认)|host(与宿主共享,类进程)|container:NAME_or_ID(与另一容器共享网络)|none
  • --restart 自动重启,可选always/on-failure,可指定尝试重启次数
  • -v 目录/文件挂载,默认rw容器内可读写,可多个目录挂载,宿主机路径:容器路径:ro
  • image:tag 镜像名:版本号,版本不指定则默认latest,大多还有stable或具体版本号
  • -e MYSQL_ROOT_PAAWORD=root设置环境变量
查看所有容器(具体容器操作大多可基于id前三位或容器名)
docker ps -a
停止/启动/重启容器
docker start/stop/restart id(3)
停止后删除容器
docker rm id(3)
查看容器详情信息
docker inspect id(3)
进入容器操作
docker exec -it id(3) /bin/bash
在容器内执行命令
docker exec cat /etc/somepath/somefile.txt
  • -i 以交互模式运行容器
  • -t 为容器分配一个伪输入终端
宿主机与容器复制文件
docker cp /home/test.txt id(3):/tmp/test.txt
docker cp id(3):/tmp/test.txt /local/tmp/test.txt
导出导入容器
docker save -o imagezip.tar myid:imagename
docker load -i imagezip.tar
docker export id(3) > imagename.tar
cat docker/imagename.tar | docker import - test/image:tag
查看容器日志
docker logs -n 5 -ft id(3)
  • -f follow保持日志刷新
  • -t 显示日志时间
  • -n number显示末尾n行
查看容器内进程[registry(container)|Harbor(UI version)]
docker top container_name
搭建私有仓库
docker pull registry
docker run -d -p 5000:5000 --restart always --name registry registry:latest
docker pull ubuntu
docker tag ubuntu newuser:5000/ubuntu
docker push newuser:5000/ubuntu
CentOS 8 安装docker及运行nginx
*CentOS默认使用了podman代替docker
1. 不卸载Podman而追加安装:
sudo yum install docker-ce docker-ce-cli containerd.io --allowerasing
2. 先卸载podman再安装docker:
yum erase podman buildah
yum install docker-ce docker-ce-cli containerd.io
3. 后台运行nginx容器
docker run -d -p 80:80 --name nginx-server -v /opt/nginx-server:/usr/share/nginx/html:rw nginx:latest
4. 创建首页文件
echo "this is nginx docker is running!" > /opt/nginx-server/index.html
5. 测试访问
[root@localhost nginx-server]# curl localhost
this is index, nginx docker is running!

运行Mysql
1. 下载镜像
docker pull mysql:8.0
2. 运行mysql容器(主节点)
docker run -d -p 3306:3306 \
--name mysqldoc \
--privileged=true \
-v /opt/mysql/log:/var/log/mysql \
-v /opt/mysql/data:/var/lib/mysql \
-v /opt/mysql/conf:/etc/mysql \
-v /opt/mysql/mysql-file:/var/lib/mysql-files \
-e MYSQL_ROOT_PASSWORD=abc123 \
mysql:8.0
3. 访问数据库(空密码?研究中)
docker exec -it mysqldoc mysql -uroot -p
4. 部署mysql从节点
docker run -d -p 3307:3306 \
--name mysql-slave \
--privileged=true \
-v /opt/mysql-slave/log:/var/log/mysql \
-v /opt/mysql-slave/data:/var/lib/mysql \
-v /opt/mysql-slave/conf:/etc/mysql \
-v /opt/mysql-slave/mysql-file:/var/lib/mysql-files \
-e MYSQL_ROOT_PASSWORD=abc123 \
--link mysqldoc:mysql-master\
mysql:8.0

运行redis
1. 下载镜像
docker pull redis
2. 运行redis
docker run -d -p 6379:6379 --name redis redis
3. 验证service运行情况
docker exec -it redis /bin/bash
redis-cli
set name abc OK
get name "abc"
自定义镜像
1. 编写dockerfile定义程序环境
#基于官方镜像开始构建,默认latest tag
FROM nginx
LABEL Image_Author=KenHuang
#设置环境变量供下面命令使用
ENV NGINX_CONFIG=/etc/nginx/conf.d/default.conf
ENV PATH=/usr/local/nginx/bin:$PATH
#构建镜像时的操作,多个RUN会占用更多资源,建议以\切割写多行
RUN sed -i "s/index.html index.htm/index.php/g" $NGINX_CONFIG \
    && sed -i "30,36 s/#//g" $NGINX_CONFIG \
    && sed -i -r "s#(cn.archive|cn.security).ubuntu.com#repo.huaweicloud.com#g" /etc/apt/sources.list \
    && apt-get update \
    && apt-get install -y php-fpm \
    && rm -rf /var/lib/apt/lists/* \
    #&& sed -i "s/^#[[:space:]+root/^root/g" $NGINX_CONFIG \
    #&& sed -i "s/^#[[:space:]+fastcgi_pass/^fastcgi_pass/g" $NGINX_CONFIG \
    #&& sed -i "s/^#[[:space:]+fastcgi_param/^fastcgi_param/g" $NGINX_CONFIG \
    #&& sed -i "s/^#[[:space:]+include/^include/g" $NGINX_CONFIG \
#复制本地项目文件进镜像内
COPY ./nginx/tpweb /usr/share/nginx/html
#需要暴露的端口,构建时-P随机分配,或-p 8080:80方式分配
EXPOSE 80
#创建一个mount点,讲容器内文件夹暴露出来,一般放置需长期保存的数据及文档
VOLUME /var/log
#启动镜像时执行的命令
CMD [ "nginx","-g","daemon off;" ]
                            
docker build ./ -t myid:imagename -f Dockerfile
docker run --name mylocsrv -d myid:imagename
2. 编写docker-compose.yml文件定义构成程序的服务
3. 在dockerfile所在目录执行docker-compose up
Sample - 部署wordpress
docker-compose up -d
CI/CD Notes
Gitlab 部署
1. 设置国内镜像
touch /etc/yum.repos.d/gitlab-ce.repo
cat /etc/yum.repos.d/gitlab-ce.repo
[gitlab-ce]
name=Gitlab CE Repository
baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el$releasever/
gpgcheck=0
enabled=1
                                    
2. 部署安装
yum install gitlab-ce --nogpgcheck
3. 修改配置
vi /etc/gitlab/gitlab.rb
external_url "http://gitlab.canwong.com"

gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "493468513@qq.com"
gitlab_rails['smtp_password'] = "updtsrthoqfxcadc"
gitlab_rails['smtp_domain'] = "qq.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_tls'] = true
gitlab_rails['gitlab_email_from'] = "493468513@qq.com"
user['git_user_email'] = "493468513@qq.com"
alertmanager['admin_email'] = '493468513@qq.com'
                                    
gitlab-ctl reconfigure
*常用控制命令
  • gitlab-ctl --help
  • gitlab-ctl status
  • gitlab-ctl restart
  • gitlab-ctl tail nginx
4. 开放/关闭防火墙
  • systemctl disable firewalld
  • systemctl stop firewalld
5. 重置管理员密码
  • gitlab-rails console
  • u=User.where(id:1).first
  • u.password='canwong123'
  • u.password_confirmation='canwong123'
  • u.save!
  • exit
6. 开机自启动
systemctl enable gitlab-runsvdir.service
Jenkins
SQL Notes
Foundation
Execute from Unix/Linux
# connect to db
mysql -hhostname -uusername -ppassword #mysql -uroot -pcanwong@123
# change password
mysqladmin -uusername -poldpassword password newpassword #mysqladmin -uroot -pcanwong@123 password newcanwong23
# execute sql file
mysql -uusername -ppassword < /path/to/sqlfile.sql
# backup database
mysqldump --opt db_name > /path/to/store/bak_filename.sql
mysqldump -uroot --all-databases --single-transaction --master-data=2 > /path/to/backup/backupfile.sql
# --databases db_name <-- specify database
# --all-databases <-- backup all databases
# --lock-all-tables  <-- for InnoDB engine hot backup
# --single-transaction <-- lock databases for InnoDB hot backup
# --master-data=[0|1|2] <--whether record master bin log location
#	0: don't record
#	1: record to 'change master to' without comment out
#	2: record to 'change master to' but comment out
                                
SQL Commands
show databases;
use database_name;
show tables;
desc table1_name -- describe table2_name; 
    create database db_name;
    create table table1_name (
    'id' int(10) NOT NULL AUTO_INCREMENT COMMENT 'descript of column',
    'pid' int(10) NOT NULL,
    'column2' varchar(1000) COMMENT 'description',
    'column3' text COMMENT 'description',
    'column3' char(10) DEFAULT '10000',
    'year' date,
    PRIMARY KEY(id),
    UNIQUE(pid),
    CHECK(id>0 AND column2='keyword')
) ENGINE=InnoDB AUTO_INCREMENT=1 CHARSET=utf8mb3;
drop db_name;
drop table table1_name;

-- Constraint
add constraint chk_rulename CHECK (column3 > 100)
drop constraint chk_rulename -- SQL Server/Oracle
drop check chk_rulename -- MySQL

-- create new user
grant select,insert,update,delete on db_name.* to new_user@localhost identified by "password";
-- select
select distinct column1,column2,column3 from table1_name where column1 like '%condition%' and column2 < 3 or column3 = 'tmp' or column4 in (value1,value2,value3) order by column1 ASC, column3 DESC;
-- update
update table1_name set column1 = 'test', column2 = 123 where id = 1000;
-- insert
insert into table1_name values ('value1','value2','value3');
insert into table1_name (column1,column2,column3) values ('value1','value2','value3');
-- truncate
truncate table table1_name;
-- delete rows
delete from talbe1_name where column1 = 'condition'; 
-- Replace
update table1_name set column1 = replace(column1,'source','replacement');
update table1_name set column2 = dbo.fn_replace_regax(column2,'^[::number::]','xxx');
update table1_name 
    set column3 = 
        CASE
            WHEN column3 LIKE '%keyword%' THEN REPLACE (column3,'keyword','new word')
            ELSE column3
        END;
-- Limit output records
    -- SQL server
    select top 100 column_name from table2_name;
    select top 20 percent * from table2_name;
    -- MySQL
    select column_name from table1_name limit 10;
    -- Oracle
    select column_name from table2_name where rownum <= 10;
-- Wildcard
    -- % <-0 or mutiple char
    -- _ <- 1 char
    -- [AbcDe] <- any char in list
    -- [^charlist] or [!charlist] <- any not in list
-- In and Between/not in/not between
select column_name from table2_name where column1 in (value1,value2,value3);
select column_name from table3_name where column2 between 10 and 20;
-- Alias
select t1.column1 as c1, t2.column2 as c2 from table1_name as t1, table2_name as t2 where t1.id = t2.pid;
                                
Expert
-- JOIN == INNER JOIN 至少有一个匹配则返回行
-- LEFT JOIN 即便右表没匹配,也从左表返回所有行
-- RIGHT JOIN 即便左表没匹配,也从右边返回所有行
-- FULL JOIN 只要其中一个表存在匹配,就返回行
select column_name from table1_name 
inner join table2_name 
on table1_name.column_name = table2_name.column_name
order by table2_name.column3;

select left_table.column1, left_table.column2, right_table.column1
from left_table
left join right_table
on left_table.id = right_table.pid
order by left_table.column2;

select left_table.column1, left_table.column2, right_table.column1
from left_table
right join right_table
on left_table.id = right_table.pid
order by left_table.column2;

-- Union 合并多个select结果集,必须有相同数量的列,列必须有相似的数据类型,同时列的顺序必须相同,会自动过滤重复结果并排序
-- Union All同上但保留重复结果并且不重新排序
select column_name from table1_name
union
select column_name from table2_name

-- Select into
select * into new_table from old_table;
select * into new_table in 'backup.mdb' from old_table; -- 向另一数据库插入
select column1,column2 into table_backup from old_table; -- 限定特定字段
select t1.column1, t2.column2 into new_table_backup from old_table as t1 inner join another_table as t2 on t1.id = t2.pid;
-- output result to file
select column1,column2 into outfile '/path/to/output_file.txt' fields terminated by ',' optionally enclosed by '"' lines terminated by '\n' from table_name1;
    -- fields terminated by 字段分隔符
    -- optinally enclosed by (可选)字段用指定字符括上
    -- lines terminated by 换行分隔符

-- Alter table
alter table table_name1 add new_column date;
alter table table_name1 drop new_column;
alter user user_name account unlock identified by "new_password";
alter table table_name1 alter column column_name int(1000);

-- View
create view view_name AS select column_name from table_name1 where column_name = 'condition';
create or replace view view_name AS select column_name from table_name1 where column_name = 'condition';
drop view view_name;

-- Functions - select function(column) from table;
select avg(column1) as new_name from table_name1;
select sum(column2) from table_name1;
select count(distinct column_name) from table_name2;
max()
min()
first()
last()
select ucase('abc');
select lcase('ABC');

-- Having - 在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与合计函数一起使用。
select column1,column2 from table_name2
where column1 = 'a' or column2 = 'b'
group by column1
having sum(column3) > 1000;

-- interview question
select name,sum(socrds) as total from students group by name order by total DESC limit 2;