苏苏的博客

简约至极

use kvm

安装和配置KVM

KVM与XEN区别

OPENVZ就不说了,是半虚拟化,不能安装Windows操作系统

KVM是内核模块,从2.6.20内核开始,kvm模块就包含在Linux内核中,只需加载此模块即可

#查看宿主机CPU是否在硬件上支持虚拟化扩展特性
cat /proc/cpuinfo | grep -E "(vmx|svm)"

#加载kvm模块(Intel VT)
modprobe kvm
modprobe kvm-intel
#注意:如果加载失败,说明服务器硬件不支持或BIOS中未开启虚拟化扩展

运行命令lsmod | grep kvm检查 KVM 模块是否成功安装

XEN是一套虚拟化方案,可以直接安装,不需要先安装操作系统.

KVM起步较晚,XEN起步早发展成熟,但目前KVM潜力较大.

KVM 与 qemu

yum install qemu-kvm libvirt virt-install bridge-utils

qemu-kvm 该软件包主要包含KVM内核模块和适用于KVM的QEMU模拟器。KVM模块负责CPU和内存的调度,QEMU负责虚拟机I/O设备的模拟。

libvirt 提供Hypervisor和虚拟机的管理功能。

virt-install 创建和克隆虚拟机的命令行工具包。

bridge-utils 网桥管理工具包,负责桥接网络的创建、配置和管理等工作。

激活并启动libvirtd服务

systemctl enable libvirtd
systemctl start libvirtd

安装CentOS7

diskutil list查看所有磁盘

diskutil unmountdisk /dev/disk1 解除其挂载

用dd将ISO文件写入

sudo dd if=/data/files/iso/CentOS-7-x86_64-Minimal-1511.iso of=/dev/disk2 bs=1m

安装好系统后,更换网易的源 http://mirrors.163.com/.help/centos.html

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
cd /etc/yum.repos.d
wget http://mirrors.163.com/.help/CentOS7-Base-163.repo
yum clean all
yum makecache

搜狐也有,但版本太老 http://mirrors.sohu.com/help/centos.html

可以使用清华大学的. https://lug.ustc.edu.cn/wiki/mirrors/help/centos 速度都十分快.

启用KVM后,需要配置网卡

cd /etc/sysconfig/network-scripts/

桥接网卡

brctl addbr br0 添加一个虚拟网卡

brctl addif br0 em2 将网卡br0桥接到em2 ,这一步将会导致em2断网,远程ssh将会断开

brctl stp br0 on 将br0设置为启用STP协议

ifconfig em2 0 #将em2的IP设置为0

dhclient br0 #将br0网络配置好

brctl show

然后systemctl restart network

route 查看默认网关

https://wiki.centos.org/zh/HowTos/KVM

创建虚拟机磁盘镜像文件

不能创建太小,建议5G-50G

qcow2格式是kvm支持的标准格式,raw格式为虚拟磁盘文件通用格式。有测试数据表明raw格式的I/O性能略高于qcow2格式,但是在加密,容量,快照方面qcow2格式有优势

qemu-img create -f qcow2 test.qcow2 20G  //建立qcow2格式磁盘文件
qemu-img create -f raw test.raw 20G      //建立raw格式磁盘文件
qemu-img info test.qcow2                 //查看已经创建的虚拟磁盘文件

创建虚拟机

使用osinfo-query os可以查看os-variant都有哪些代号

https://raymii.org/s/articles/virt-install_introduction_and_copy_paste_distro_install_commands.html

创建 Ubuntu

virt-install \
--name ubuntu \
--ram 512 --vcpus 1 \
--boot network,cdrom,menu=on \
--disk path=/disk/kvm/disk1,size=10,format=qcow2,bus=virtio \
--os-type linux \
--os-variant generic \
--nographics --accelerate \
--bridge=br0,model=virtio --keymap=en-us \
--console pty,target_type=serial \
--cdrom=/data/iso/ubuntu-16.04.1-server-amd64.iso \
--extra-args='console=tty0 console=ttyS0,115200n8 serial' \
--hvm --dry-run

创建CentOS

virt-install \
--name centos \
--ram 512 --vcpus 1 \
--disk path=/disk/kvm/disk1,size=10,format=qcow2,bus=virtio \
--os-type linux \
--os-variant generic \
--accelerate \
--bridge=br0,model=virtio --keymap=en-us \
--console pty,target_type=serial \
--location=/data/iso/CentOS-7-x86_64-Minimal-1511.iso \
--extra-args='console=tty0 console=ttyS0,115200n8 serial' \
--hvm --dry-run

virsh –connect qemu:///system

创建Debain

先挂载 sudo mount -o loop,unhide -t iso9660 -r /data/iso/debian-8.6.0-amd64-CD-1.iso /mnt/cdrom

需要nfs启动 service nfs start

添加/mnt/cdrom *(ro,insecure,all_squash)到文件/etc/exports

并刷新exportfs -r

virt-install \
--name debain \
--ram 512 --vcpus 1 \
--boot network,cdrom,menu=on \
--disk path=/disk/kvm/disk4,size=10,format=qcow2,bus=virtio \
--os-type linux \
--os-variant generic \
--bridge=br0,model=virtio --keymap=en-us \
--console pty,target_type=serial \
--accelerate \
--location=/mnt/cdrom \
--extra-args='console=tty0 console=ttyS0,115200n8 serial' \
--vnc --vncport=5911 --vnclisten=0.0.0.0 \
--hvm --dry-run

创建Windows Server

qemu-img create -f qcow2 /disk/kvm/windisk1 50G

针对Windows需要安装一些驱动

sudo wget https://fedorapeople.org/groups/virt/virtio-win/virtio-win.repo -O /etc/yum.repos.d/virtio-win.repo

sudo yum install virtio-win

https://fedoraproject.org/wiki/Windows_Virtio_Drivers

virt-install \
--name windows2012 \
--ram 4096 --vcpus 2 \
--disk path=/data/iso/cn_windows_server_2012_r2_with_update_x64_dvd_4048415.iso,device=cdrom \
--disk path=/disk/kvm/windisk1,size=50,format=qcow2,bus=virtio,cache=writeback \
--cdrom=/usr/share/virtio-win/virtio-win-0.1.126.iso \
--os-type windows \
--os-variant win2k12r2 \
--bridge=br0,model=virtio \
--accelerate \
--graphics vnc,port=5999,listen=0.0.0.0 \
--console pty,target_type=serial \
--hvm --dry-run
virt-install \
--name xp1 \
--ram 1024 --vcpus 1 \
--disk path=/data/iso/Deepin_Windows_LiteXP_v6.2_SP3.iso,device=cdrom \
--disk path=/disk/kvm/winxp1,size=10,format=qcow2,bus=virtio,cache=writeback \
--cdrom=/usr/share/virtio-win/virtio-win-0.1.126.iso \
--os-type windows \
--os-variant winxp \
--bridge=br0,model=virtio \
--accelerate \
--graphics vnc,port=5999,listen=0.0.0.0 \
--console pty,target_type=serial \
--hvm --dry-run

出现ERROR 不能混用 --graphics 和旧式的图形选项可能是需要去掉--keymap

关于 加载 virtio 驱动可以参考 http://www.ilanni.com/?p=5877

选择加载viostor磁盘驱动

disk属性就是指虚拟机使用哪一个磁盘镜像文件作为存储地方,指定刚才创建的镜像文件位置即可,size=10,format=qcow2,bus=virtio分别是指大小,格式(跟镜像格式一致),磁盘总线类型(指Value can be ’ide’, ’scsi’, ’usb’, ’virtio’ or ’xen’,virtio是专门为kvm制定的bus,比较常用),大小需要比镜像文件大小要小,相当于镜像是容器,这个disk是里面的水,水太多就溢出了。

bridge=br0,model=virtio –keymap=en-us分别指网卡使用,网卡模式即驱动模式,和键盘制式,桥接模式都使用br0,而虚拟机需要使用virtio这个驱动才能使用虚拟网卡,这个虚拟网卡驱动在linux下支持很好,在windows下支持一般,键盘制式如果不指定的话会出现键位错乱的情况,一般我们使用英式。

使用virsh可以管理已创建的虚拟机

virsh shutdown demo 正常关闭虚拟机

virsh destroy demo 直接销毁虚拟机

可见 http://www.cnblogs.com/lin1/p/5776280.html

启动并进入虚拟机

virsh start 域名 --console

10,彻底删除虚拟机

1,删除虚拟机 virsh destroy +域名

2,解除标记 virsh undefine +域名

3,删除虚拟机文件

virsh destroy windows2012 && virsh undefine windows2012

通过virt-clone命令克隆虚拟机

virt-clone -o centos -n centos2 -f /disk/kvm/disk2

virsh -c qemu:///system list 可以查看正在运行的机器

virsh vncdisplay windows2012查看vnc端口

可以使用其他机器上的vnc viewer 连接

本机 virt-viewer --connect qemu:///system windows2012

windows系统可使用 vncviewer (http://share.suconghou.cn/files/bin/vncviewer.zip) 连接

全屏下用F8键可唤出菜单.

修改相关

hostnamectl 可以查看主机相关信息,主机名,内核版本,64位等

只查看静态、瞬态或灵活主机名,分别使用--static,--transient--pretty选项

要同时修改所有三个主机名:静态、瞬态和灵活主机名: hostnamectl set-hostname Linuxidc

hostname -I 可以获取所有网卡上配置的IP

iptables与firewalld

iptables相关配置

配置iptables之前,建议添加一个crontab定时重置iptables,防止将自己阻挡.

建议写入/usr/iptab.sh,加入crontab,每个整点执行

iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
iptables -X
iptables -Z

查看本机关于IPTABLES的设置情况

iptables -L -n

清除原有规则.

不管你在安装linux时是否启动了防火墙,如果你想配置属于自己的防火墙,那就清除现在filter的所有规则. 清除预设表filter中的所有规则链的规则

iptables -F

清除预设表filter中使用者自定链中的规则

iptables -X

保存配置

刚刚配置的重启以后就会丢失,想要保存使用

iptables save

有的可能是iptables-save

这样就写到/etc/sysconfig/iptables 文件里了. 写入后记得把防火墙重起一下,才能起作用.

service iptables restart

设定预设规则

默认的入口,出口,转发策略都是ACCEPT 下面要改变这种规则

iptables 采用黑名单加白名单的方式, 未命中白名单的将采用预设规则

下面操作注意,为避免ssh端口22被拦截,首先添加

iptables -A INPUT -p tcp --dport 22 -j ACCEPT

保证22端口入口畅通,注意如果你的OUTPUT模式设置为DROP(上面已经清空了,默认为ACCEPT),还需要添加

iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT

保证出口22端口畅通 下面开始折腾吧

1.修改入口流量默认规则为DROP,除非命中用户规则,否则拦截所有入口流量(注意上面一定要排除ssh的端口,否则直接掉线)

iptables -P INPUT DROP

如果你使用了docker,这里好像会对docker的网络造成影响

2.允许所有出口流量(重置iptables时,这其实就是默认的规则)

iptables -P OUTPUT ACCEPT

3.禁止所有转发流量,除了命中用户规则的

iptables -P FORWARD DROP

常用端口开启

开启80,443端口,http,https服务

iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

开启21端口,ftp服务

iptables -A INPUT -p tcp --dport 21 -j ACCEPT

开启基本端口

允许icmp包通过,也就是允许ping

iptables -A INPUT -p icmp -j ACCEPT

允许loopback!(不然会导致DNS无法正常关闭等问题)

如果未启用此项,常见的fastcgi_pass 127.0.0.1 将会有问题

iptables -A INPUT -i lo -p all -j ACCEPT

iptables 配置实时生效,如果拦截了ssh端口,将立即掉线!

无论iptabes启动与否,ps -ef都不会看到iptables的进程,这是因为iptables是由内核来实现的,也就是说iptables的功能已经融入到内核里面了

iptables只是一个工具,将IP规则写入内核,让内核去处理。所以iptables只有在加规则的时候才会看得到进程,加完了就退出了

iptables并不是一个普通的daemon,只是一个普通的工具,添加一些规则到kernel的filter列表里面。

systemctl stop iptables 也与进程无关,他只是执行了/usr/libexec/iptables/iptables.init stop

将规则从内核清除到存到文件.

IP 拦截

拦截一个IP

iptables -I INPUT -s 1.2.3.4 -j DROP

解封此IP

iptables -D INPUT -s 1.2.3.4 -j DROP

参数-I是表示Insert(添加),-D表示Delete(删除)

INPUT表示入站,DROP表示放弃连接

IP段

192.168.1.x 可以写 192.168.1.0/24

192.168.x.x 可以写 192.168.0.0/16

192.x.x.x 可以写 192.0.0.0/8

iptables -I INPUT -s 112.198.0.0/16 -j DROP

iptables 过滤大量IP地址任然是挨个遍历,如需拦截数以万计的IP地址,需使用ipset,能获取最佳性能. yum info ipset -y 安装ipset

路由黑洞

linux 黑洞路由命令 net-tool 用法 route add -host 10.10.0.1 127.0.0.1 -blackhole iprouter2 用法 ip route add blackhole 192.168.32.128/32

中国 ip 段获取

wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' | awk -F\| '/CN\|ipv4/ { printf("%s/%d\n", $4, 32-log($5)/log(2)) }' > ./ignore.list

端口转发

允许服务器的IP转发功能: echo 1 > /proc/sys/net/ipv4/ip_forward

iptables -t nat -A POSTROUTING -j MASQUERADE

iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 31521 -j DNAT --to 192.168.0.211:1521

相同端口后面可省略不写 iptables -t nat -I PREROUTING -p tcp --dport 1521 -j DNAT --to 192.168.0.211


#清除配置
/sbin/iptables -P INPUT ACCEPT
/sbin/iptables -F
/sbin/iptables -X
#开放本地和Ping
/sbin/iptables -A INPUT -i lo -j ACCEPT
/sbin/iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
/sbin/iptables -A INPUT -p icmp -j ACCEPT
#配置内网白名单
/sbin/iptables -A INPUT -s 10.0.0.0/8 -j ACCEPT
/sbin/iptables -A INPUT -s 172.16.0.0/12 -j ACCEPT
/sbin/iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT
#配置外网白名单
/sbin/iptables -A INPUT -s 180.168.36.198 -j ACCEPT
/sbin/iptables -A INPUT -s 180.168.34.218 -j ACCEPT
/sbin/iptables -A INPUT -s 222.73.202.251 -j ACCEPT
#控制端口
/sbin/iptables -A INPUT -p tcp --dport 80 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -j ACCEPT
#拒绝其它
/sbin/iptables -A INPUT -j DROP
/sbin/iptables -A FORWARD -j DROP
#开放出口
/sbin/iptables -A OUTPUT -j ACCEPT

参考 http://liaoph.com/iptables/

firewalld

systemctl status firewalld 查看服务状态

firewall-cmd --state 常看当前的状态

firewall-cmd --get-active-zones 查看区域信息

查看某区域打开的端口 firewall-cmd --zone=public --list-ports 添加一个开放端口

firewall-cmd --zone=public --add-port=8080/tcp

add-port 后只是本次生效,并没有保存到配置文件内,执行firewall-cmd --reload未保存到配置文件内的就丢失了.

需要永久生效时,添加需加上--permanent,如 firewall-cmd --permanent --zone=public --add-port=9090/tcp

更多可参考 http://www.ywnds.com/?p=7570&viewuser=30 https://linux.cn/article-8098-1.html

pc hardware

修电脑相关知识

较好的PE

微PE

http://www.wepe.com.cn/ 自带刻录,可以一键安装到U盘,硬盘等,支持UEFI,CMS等多种启动方式.

一般的BIOS里找不到UEFI/CMS的切换设置,可能是security boot的配置,禁用security boot试试

如果在BIOS里找不到U盘,可能是fastboot的问题,可以禁用fastboot,安装好系统后在开启.

硬盘的设置模式里,找不到U盘或者硬盘,可以尝试切换AHCI/IDE,注意安装好系统后,此选项不能够再随意切换,否知导致系统进不去.

休眠能将现有所有工作保存到硬盘,下次开机恢复上次的会话,Windows8及以后采用了混合休眠机制

你可能找不到单纯的休眠按钮.

可以使用shutdown -h休眠

其他一些补充

关机计算机:shutdown.exe -s -t 00
重启计算机:shutdown.exe -r -t 00
注销计算机:shutdown.exe -l -t 00
锁定计算机:rundll32.exe user32.dll,LockWorkStation
休眠计算机:rundll32.exe powrProf.dll,SetSuspendState
睡眠计算机:rundll32.exe powrprof.dll,SetSuspendState 0,1,0,

性能天梯图

CPU性能列表 https://www.cpubenchmark.net/cpu_list.php

在新标签查看大图

CPU天梯图

CPU天梯图1

CPU天梯图其他版本

CPU天梯图2

显卡天梯图

显卡天梯图

memcached usage

安装memcached

http://memcached.org/downloads

memcached所有版本见http://www.memcached.org/files/

cd /tmp
MEMCACHE_VERSION=memcached-1.5.1
CPU_NUM=`cat /proc/cpuinfo | grep processor | wc -l`
wget http://www.memcached.org/files/${MEMCACHE_VERSION}.tar.gz
tar xzf ${MEMCACHE_VERSION}.tar.gz
cd ${MEMCACHE_VERSION}
export CFLAGS="-O3"
./configure
make -j$CPU_NUM && make install

docker版本见:https://hub.docker.com/r/suconghou/memcached/

静态编译

apk update && apk upgrade && apk add gcc g++ make wget
wget --no-check-certificate https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/libevent-2.1.8-stable.tar.gz
tar zxf libevent-2.1.8-stable.tar.gz
cd libevent-2.1.8-stable
./configure && make && make install

libevent编译很快,不到一分钟

cd /tmp
MEMCACHE_VERSION=memcached-1.5.1
wget http://www.memcached.org/files/${MEMCACHE_VERSION}.tar.gz
tar xzf ${MEMCACHE_VERSION}.tar.gz
cd ${MEMCACHE_VERSION}
export CFLAGS="-O3"
./configure --disable-docs
make LDFLAGS=-static && make install

启动Memcached

memcached -d -u memcached -p 11211 -m 8 -P /var/run/memcached/memcached.pid

说明

  • -d 以daemon方式运行
  • -u 绑定使用指定用户运行进程(仅在以root运行的时候有效)
  • -p 设置TCP端口号(默认11211)
  • -m 允许最大内存用量,单位M (默认: 64 MB)
  • -M 内存耗尽时返回错误,而不是删除项
  • -l 是监听的服务器IP地址,默认应该是本机
  • -P 将PID写入文件,这样可以使得后边进行快速进程终止, 需要与-d 一起使用
  • -c 最大同时连接数,默认是1024
  • -t 线程数,默认为4
  • -v 输出警告和错误信息
  • -vv 打印客户端的请求和返回信息

默认情况下是不限制访问IP的,相当于是外网和内网都能访问,-l 使只有这个IP能访问

尽量不要用root用户运行.

状态查看

使用 telnet 连接 memcached stats settings可以查看所有参数设置

memcached状态和性能查看

stats命令

memcached stats命令

官方也提供监控工具

https://github.com/memcached/memcached/blob/master/scripts/memcached-tool

javascript code snippet

实用的Javascript代码锦集

Date.parse("2016-04-4")

Date.parse safari 不能使用单位数字的月份和日期,否则解析为NaN

火狐较低版本(火狐43)也是如此

+new Date('2017-06-08 21:00:00');IE11上得出NaN Safari10 上也得出NaN Chrome 和 Firfox下OK 原因在于 IE 和 Safari 都不识别以-分割的日期 需要写成 +new Date('2017/06/08 21:00:00'); , 这样才能在所有浏览器兼容.

IE10 has not anchorNode focusNode 属性, 取得选中的文字需要读取 text 属性, IE11 一切正常 , 取得选中文字可以直接 toString

IE10,IE11 不支持 html5 的 download 属性, 无法点击下载自定义名称的html和图片等文件. 可以使用 下载的 downloadFile,利用ajax下载,顺便说 ajax 下载也不能使用fetch IE系统统不支持fetch,到EDGE14才支持fetch, https://github.com/github/fetch 可支持IE10+

火狐不支持和chrome的scrollTop表现也不相同

// 兼容处理 chrome 和 firefox
let scrollTop=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop;
if(scrollTop<20){
    this.headerShowStatus=true;
}else if(scrollTop>170){
    this.headerShowStatus=false;
}
if(document.documentElement.scrollHeight-scrollTop- document.documentElement.clientHeight< 400 ){
    this.loadMore();
}

火狐不支持 e.srcElement 需要使用 e.target 代替

IE10,IE11, 不支持location.origin

var origin = location.origin?location.origin:location.protocol+"//"+location.host;

firefox 浏览器下载接受的后端header 不支持单引号

旧版firefox 不支持insertAdjacentElement,直到火狐48才支持

https://gist.github.com/kafene/8e56adaf3c1ca4188938

if ("undefined" === typeof (Element.prototype.insertAdjacentElement)) {
    Object.defineProperty(Element.prototype, "insertAdjacentElement", {
        enumerable: false,
        writable: true,
        configurable: true,
        value: function (position, elem) {
            switch (position.toString().toUpperCase()) {
                case "BEFOREBEGIN":
                    return this.parentNode.insertBefore(elem, this);
                case "AFTERBEGIN":
                    return this.insertBefore(elem, this.firstChild);
                case "BEFOREEND":
                    return this.appendChild(elem);
                case "AFTEREND":
                    return this.parentNode.insertBefore(elem, this.nextSibling);
                default:
                    throw new Error("Invalid element position `" + position + "`");
            }
        }
    });
}

safari8 safari10 对于父元素是border-radius,overflow:hidden;

子元素可以被父元素相切,只显示父元素相切后的内容, 但是子元素如果使用了keyframe帧动画,则出现bug,相切的并不是border-radius后的结果.

IE

word-wrap: break-word; 文字换行, Chrome,Safari,Firefox 无论中英文,还是超长英文单词,都能够自动换行不溢出.

但是IE10,IE11对于超长单词仍然溢出,需要添加word-break: break-all;

chrome 31 or 搜狗5.0.9 (2014年)

chrome 31 内核 bug , supports 函数不能赋值给其他变量执行

var support = (window.CSS && window.CSS.supports) || window.supportsCSS || false;
if(support){
    return support('-webkit-text-decoration-style','wavy')||support('text-decoration-style','wavy');
}
return false;

如上,会报TypeError:Illegal invocation

可修改为如下

 if(window.CSS&&window.CSS.supports){
    return window.CSS.supports('-webkit-text-decoration-style','wavy')||window.CSS.supports('text-decoration-style','wavy');
}else if(window.supportsCSS){
    return window.supportsCSS('-webkit-text-decoration-style','wavy')||window.supportsCSS('text-decoration-style','wavy');
}else{
    return false;
}

异步之中的下载文件

在异步中使用window.open是无法生效的

发现异次元的下载链接

使用 form.submit 向后端提交下载地址 (不要使用target _blank) ,后端302即可实现异步调用文件下载

还可以使用定时器设定打开任务,然后ajax回调后设定变量

window.opener

window.open 打开同源网站,目标站点可访问 window.opener, 且可操作其opener各种属性和方法

对应打开的非同源网站, 目标站点不能读取 opener的信息,如 location.href. 出现跨域问题,但是可以调用 window.opener.location.replace/assign 等 , 让原网站跳转指定url.

获取查询查询字符串get参数值

function getParam()
{
	var data = decodeURIComponent(location.href).split("?")[1].split("&");
	var param = {};
	for(var i = 0; i<data .length; i++)
	{
		param[data [i].split("=")[0]] = data [i].split("=")[1];
	}
	return param;
}

类似于PHP中的$_GET

var $_GET = (function()
{
	var url = decodeURIComponent(location.href);
	var u = url.split( "?" );
	if ( typeof (u[1]) == "string" )
	{
		u = u[1].split( "&" );
		var get = {};
		for ( var i in u)
		{
			var j = u[i].split( "=" );
			get[j[0]] = j[1];
		}
		return get;
	}
	else
	{
		return {};
	}
})();

给出要获取的参数,每次都会解析一遍

function getPar(par)
{
	//获取当前URL
	var local_url = decodeURIComponent(location.href);
	//获取要取得的get参数位置
	var get = local_url.indexOf(par + "=" );
	if (get == -1)
	{
		return false ;
	}
	//截取字符串
	var get_par = local_url.slice(par.length + get + 1);
	//判断截取后的字符串是否还有其他get参数
	var nextPar = get_par.indexOf( "&" );
	if (nextPar != -1)
	{
		get_par = get_par.slice(0, nextPar);
	}
	return get_par;
}

QueryString

function QueryString(item)
{
	var value = location.search.match(new RegExp('[\?\&]' + item + '=([^\&]*)(\&?)','i'));
	return value ? value[1] : value;
}

Cookie操作

function setCookie(cookiename, cookievalue, hours)
{
	var date = new Date();
	date.setTime(date.getTime() + Number(hours) * 3600 * 1000);
	document.cookie = cookiename + "=" + cookievalue + "; path=/;expires = " + date.toGMTString();
}

取得Cookie中某个键的值

$.getCookie = function(name)
{
	 if(document.cookie.indexOf(name)!=-1) return document.cookie.split(name+'=')[1].split(';')[0]
}

另一个

function getcookie(cookieid)
{
	//获取cookie字符串
	var strCookie=document.cookie;
	//将多cookie切割为多个名/值对
	var arrCookie=strCookie.split("; ");
	var cookieval;
	//遍历cookie数组,处理每个cookie对
	for(var i=0;i<arrCookie.length;i++)
	{
		var arr=arrCookie[i].split("=");
		//找到名称为userId的cookie,并返回它的值
		if(cookieid==arr[0])
		{
			cookieval=arr[1];
			break;
		}
	}
	return(cookieval);
}

类似于 php 中 http_build_query

jQuery 中的 $.param

var params = {
    parameter1: 'value_1',
    parameter2: 'value 2',
    parameter3: 'value&3'
};

var esc = encodeURIComponent;
var query = Object.keys(params).map(k => esc(k) + '=' + esc(params[k])).join('&');

进入全屏

function gofull()
{
	var el=document.documentElement;
	el.webkitRequestFullScreen&&el.webkitRequestFullScreen();
	el.mozRequestFullScreen&&el.mozRequestFullScreen();
	el.requestFullscreen&&el.requestFullscreen();
}

字符串去空格

String.prototype.trim=function() {return this.replace(/(^\s*)|(\s*$)/g,""); }
String.prototype.ltrim=function(){return this.replace(/(^\s*)/g,""); }
String.prototype.rtrim=function(){return this.replace(/(\s*$)/g,""); }

字节格式化

function size(size)
{
	var name=['B','KB','MB','GB','TB','PB'];
	var pos=0;
	while(size>=1204)
	{
	    size/=1024;
	    pos++;
	}
	return size.toFixed(2)+" "+name[pos];
}

判断页面滚动到底部和顶部

$(document).scroll(function()
{
	if ($(document).scrollTop()<=0)
	{
		console.log("滚动条已经到达顶部为0");
	}
	if ($(document).scrollTop() >= $(document).height() - $(window).height())
	{
		console.log("滚动条已经到达底部为" + $(document).scrollTop());
	}
});

运行JS代码

// execute code in the content page scope
var injectScript = function(source) {
    var script = document.createElement('script');
    script.setAttribute('type', 'text/javascript');
    script.textContent = ';(' + source.toString() + ')()';
    document.body.appendChild(script);
    document.body.removeChild(script)
}

添加CSS代码

// insert css
function injectStyle(css) {
    var script = document.createElement('style')
    script.setAttribute('type', 'text/css')
    script.textContent = css
    document.head.appendChild(script)
}

利用注释,可也生成html,css,js 等代码

(function(){/* body{background:#f00} */}).toString().slice(15,-4)

当然利用es6的字符串模板更加方便,http://babeljs.io/repl/ 在线转换为es5代码

一些正则验证

验证邮箱

function is_mail(str)
{
	return(new RegExp(/^[0-9a-zA-Z]+@(([0-9a-zA-Z]+)[.])+[a-z]{2,4}$/i).test(str));
}

验证手机号

function is_tel(str)
{
	return(new RegExp(/^1[34578][0-9]{9}$/).test(str));
}

Base64的1x1像素间隔gif

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">

一个range函数

function range(start, count)
{
	return Array.apply(0, Array(count)).map(function (element, index)
	{
		return index + start;
	});
}

简化console.log

var log = console.log.bind(console);

生成较短的唯一ID

一定年限内单线程非连续调用唯一

function shortId()
{
	var time=Date.now()+'';
	time=parseInt(time.substr(1));
	return time.toString(36);
}

生成随机短ID,仅具备较低的不重复性

var t=(((1+Math.random())*0x10000000)|0).toString(16);

生成指定长度随机字符串 PHP代码

function code($nc, $a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
{
    $l=strlen($a)-1; $r='';
    while($nc-->0) $r.=$a{mt_rand(0,$l)};
    return $r;
}

给jQuery的form添加serializeObject

jQuery.prototype.serializeObject=function()
{
	var a,o,h,i,e;
	a=this.serializeArray();
	o={};
	h=o.hasOwnProperty;
	for(i=0;i<a.length;i++)
	{
		e=a[i];
		if(!h.call(o,e.name))
		{
			o[e.name]=e.value;
		}
	}
	return o;
};

使用效果如下

jQuery("form").serialize(); //"username=&password="
jQuery("form").serializeArray(); //[{name:"username",value:""},{name:"password",value:""}]
jQuery("form").serializeObject(); //{username:"",password:""}

直接下载blob数据

function downFile(blob, fileName)
{
    if (window.navigator.msSaveOrOpenBlob)
    {
        navigator.msSaveBlob(blob, fileName);
    }
    else
    {
        var link = document.createElement('a');
        link.style.display='none';
        link.href = window.URL.createObjectURL(blob);
        link.download = fileName;
        document.body.appendChild(link);
        link.click();
        setTimeout(function()
        {
            document.body.removeChild(link);
            window.URL.revokeObjectURL(link.href);
        },200);
    }
}

兼容IE,Chrome,Firefox,Safari,注意 appendChild 这一步不能缺,否则Firefox不兼容

var blob = new Blob([res.data], {type: "application/vnd.ms-excel"}),
    fileName = '下载.xls';
downFile(blob, fileName);
fetch('/files/bin/http.xz').then(res=>res.blob()).then(res=>{console.log(res);downFile(res,"http.xz")})

iso 8 html5 canvas 限制

https://stackoverflow.com/questions/18565395/why-does-canvas-context-drawimage-fail-on-iphone

ios 的canvas 有像素限制,由于像素过大,实测拍出来的图片不能使用 canvasContext.drawImage处理.

现象是canvas画出来的图片为空白,toBlob和toDataUrl也不能取到该canvas的数据.

解决方案

https://github.com/stomita/ios-imagefile-megapixel (未测试)

还有更加全面的方案

https://github.com/blueimp/javascript-load-image

加上 https://github.com/blueimp/JavaScript-Canvas-to-Blob

能更加方便的处理图片,实测可以解决拍出的图片过大无法处理的问题.

https://blueimp.github.io/JavaScript-Load-Image/ 提供在线检查Exif meta data

资源预取

function prefetch(url)
{
	var link = document.createElement("link");
	link.href = url;
	link.rel="prefetch";
	document.head.appendChild(link);
}

Google Analytics统计JS错误

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
window.addEventListener('error', function (err)
{
	ga('create', 'UA-xxx-1', 'auto');
    var lineAndColumnInfo = err.colno ? ' line:' + err.lineno +', column:'+ err.colno : ' line:' + err.lineno;
    ga('send', 'event', 'JavaScript Error', err.message, location.href+' => '+err.filename + lineAndColumnInfo + ' -> ' +  navigator.userAgent, 0, true );
});

UA-xxx-1使用自己的统计ID

jQuery并发发送ajax

$.when($.get('assets/misc/1.json'), $.get('assets/misc/2.json')).then(function(r1, r2)
{
    console.log(r1[0].message + " " + r2[0].message);
})

微信内JS获取地理位置

<script type="text/javascript" src="https://apis.map.qq.com/tools/geolocation/min?key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77&referer=mywxapp"></script>

获取精确定位信息
var options = {timeout: 9000};
geolocation.getLocation(showPosition, showErr, options);

粗糙定位信息
geolocation.getIpLocation(showPosition, showErr)

Fetch跨域带cookie

fetch(url, {credentials: 'include'})

jQuery ajax 跨域带 cookie

$.ajaxSetup({xhrFields: {withCredentials: true }});
音乐标题
歌手