0%

在linux平台上,有很多优秀的shell命令组合来做多文件查找/替换,比如这些命令:find,sed,grep,awk,perl。但其他平台比如windows上就没那么方便了,这时候vim内置的多文件查找命令就有用武之地了,虽然比起外部命令来稍微慢了一点点儿。

这个vim内置命令就是vimgrep,有两种基本的使用方式:

1
2
:vim\[grep\]\[!\] /{pattern}/\[g\]\[j\] {file} ...
:vim\[grep\]\[!\] {pattern} {file} ...

file部分支持通配符,代表当前目录,**代表当前目录及其子目录(递归),比如/.c代表当前目录下的c源程序文件,**/.c代表当前目录及其递归子目录下的所有源程序文件。file部分可以指定多次。

g(global)是全局标志,没有g,每行只会匹配一次,如果有g,则匹配行内所有符合的pattern,也就是行可以会多次被添加到quickfix列表。
j(jump)是跳转标志,没有j,vim会跳转到第一个匹配,如果有j,则只更新

以下命令查看匹配结果:

1
2
3
:cn\[ext\] 下一个结果
:cp\[revious\] 上一个结果
:cw\[indow\] quickfix窗口,结果文件列表

更详细的用法参见:help vimgrep 和下面的refs。

References:
[1]使用vimgrep查找文件
[2]vi/vim使用进阶: 剑不离手 – quickfix

===
[erq]

uniq命令隔行重复是不认的,所以对于隔行重复的情况需要先用sort命令进行排序。

linux平台上virtualbox客户机如果需要访问主机的usb设备,则必须要将启动virtualbox主机的用户添加到vboxusers用户组。

最近使用带有firmware的debian netinst安装一台服务器时,安装进度到99%配置console-setup时进程停滞了,没有当机,只是进度不动,几个小时都不带动的,一直在:

1
configuring console-setup...

CTRL+ALT+4查看安装日志,也没有错误提示,只是在等待。
重启进入rescue安装模式,在instaler环境下执行

1
# dpkg --configure -a

console-setup配置界面选择# american,安装时就是因为这里自动配置没过去,从而无限停滞了。

之后执行

1
# grub-installer

出现类似如下错误:

1
2
3
Media change: please insert the disc labeled
'Debian GNU/Linux ... Official amd64 CD Binary-1 ...'
in the drive '/media/cdrom/' and press enter

无果。

其实大部分包已经装完了,只是还没有安装grub,配置root用户和添加新用户而已。
所以使用rescuecd引导系统安装grub
这时候root是没密码的,无法正常登录,grub引导时选择recovery模式,顺利以root登录系统,然后执行passwd命令为root设置密码,之后再添加普通用户即可。

如果执行chroot时遇到这个错误,chroot: failed to run command `/bin/bash': Exec format error,极有可能是因为两个环境的架构不一致,比如X86和AMD64。

原来RTL8723AU芯片上的蓝牙功能驱动也已经有了,还是那个热心的Larry W. Finger搞的,github地址在https://github.com/lwfinger/rtl8723au_bt

安装也很简单:

1
2
3
4
5
$ git clone https://github.com/lwfinger/rtl8723au_bt
$ cd rtl8723au_bt
$ make
# make install
# modprobe rtk_btusb

然后就可以了

UPDATE(08/01/2015):
hci_recv_fragment函数从kernel 3.18起被删除了,当前仓库的master分支尚未修改以支持此状况,但kernel分支已经支持。因此应该切换到kernel分支再行编译安装。
并且,模块的名字变成了btusb, so:

1
2
3
$ git checkout kernel
...
# modprobe btusb

就可以了。

===
[erq]

jps
JVM版的ps命令,主要参数有:

  • -l
    输出完整的包名或者应用程序jar文件的全路径名
  • -m
    输出传给main方法的参数
  • -v
    输出传给JVM的参数
1
2
$ sudo jps -lmv grep -v Jps
738 org.apache.catalina.startup.Bootstrap start -Djava.util.logging.config.file=/var/lib/tomcat8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.awt.headless=true -Xmx128m -XX:+UseConcMarkSweepGC -Djava.endorsed.dirs=/usr/share/tomcat8/endorsed -Dcatalina.base=/var/lib/tomcat8 -Dcatalina.home=/usr/share/tomcat8 -Djava.io.tmpdir=/tmp/tomcat8-tomcat8-tmpJVM版的ps命令

jps命令的输出格式为:

1
lvmid \[ \[ classname JARfilename "Unknown"\] \[ arg* \] \[ jvmarg* \] \]

第一个列的lvmid是本地JVM标识符,同时也就是JVM进程的进程号。

jps命令只会输出当前执行命令的用户有权限访问的JVM进程信息。所以就是root也不一定能读取JVM进程信息,比如访问tomcat8的JVM信息要这样:

1
2
3
$ sudo -u tomcat8 jps -lvm
25768 sun.tools.jps.Jps -lvm -Dapplication.home=/usr/lib/jvm/jdk-8-oracle-x64 -Xms8m
25151 org.apache.catalina.startup.Bootstrap start -Djava.util.logging.config.file=/var/lib/tomcat8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.awt.headless=true -Xmx3072m -Xms3072m -Xmn2048m -XX:PermSize=2048m -XX:MaxPermSize=3072m -XX:+UseConcMarkSweepGC -Djava.endor

用root用户也看不到详细信息:

1
2
3
4
5
$ sudo jps -lvm
25809 sun.tools.jps.Jps -lvm -Dapplication.home=/usr/lib/jvm/jdk-8-oracle-x64 -Xms8m
11806 -- process information unavailable
9998 -- process information unavailable
25151 -- process information unavailable

因为临时文件/tmp/hsperfdata_{user}/目录下的文件只有{user}才有存取权限。

jinfo
查看JVM的所有配置信息和命令行标志,还可以动态设置JVM的命令行标志参数。详细用法见jinfo(1)。
如果出现:

1
pid: well-known file is not secure 

说明当前用户没有相应的权限,情使用与JVM进程相同的用户或者root用户再次尝试命令

如果出现:

1
2
3
4
5
6
Exception in thread "main" java.io.IOException: Command failed in target VM
at sun.tools.attach.LinuxVirtualMachine.execute(LinuxVirtualMachine.java:224)
at sun.tools.attach.HotSpotVirtualMachine.executeCommand(HotSpotVirtualMachine.java:217)
at sun.tools.attach.HotSpotVirtualMachine.setFlag(HotSpotVirtualMachine.java:190)
at sun.tools.jinfo.JInfo.flag(JInfo.java:129)
at sun.tools.jinfo.JInfo.main(JInfo.java:76)

说明不支持配置此参数。

jstat
JVM版的vmstat命令,JVM内存使用统计监控工具,可以监控各类内存使用量,也可以按时间间隔连续输出进行监控。详细用法参见jstat(1)和参考[1]

列如,查看VM内存中三代(young,old,perm)对象的使用和占用大小

1
2
3
$ sudo jstat -gccapacity lvmid
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC
20672.0 43648.0 43648.0 4352.0 4352.0 34944.0 41408.0 87424.0 87424.0 87424.0 21248.0 169984.0 90476.0 90476.0 271 24

jmap
查看JVM中所有对象使用内存资源的详细情况,详细用法见jmap(1)

1
jmap \[ option \] lvmid

查看JVM堆使用情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ sudo -u tomcat8 jmap -heap 4891
Attaching to process ID 4891, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.65-b04

using parallel threads in the new generation.
using thread-local object allocation.
Concurrent Mark-Sweep GC

Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 134217728 (128.0MB)
NewSize = 1310720 (1.25MB)
MaxNewSize = 44695552 (42.625MB)
OldSize = 5439488 (5.1875MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 21757952 (20.75MB)
MaxPermSize = 174063616 (166.0MB)
G1HeapRegionSize = 0 (0.0MB)
...

jstack
Java 栈追踪,用法详见jstack(1)

1
jstack \[ option \] pid
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ sudo -u tomcat8 jstack 4891
2014-11-06 10:30:21
Full thread dump OpenJDK 64-Bit Server VM (24.65-b04 mixed mode):

"Attach Listener" daemon prio=10 tid=0x00007f2174001000 nid=0x165f waiting on condition \[0x0000000000000000\]
java.lang.Thread.State: RUNNABLE

"http-nio-80-exec-10" daemon prio=10 tid=0x00007f213800a800 nid=0x135a waiting on condition \[0x00007f2161e16000\]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000f06fe518> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
...

jconsole
jconsole是JMX兼容的java监视和管理控制台。可以查看JVM上运行程序的性能和资源占用情况。
当使用jconsole监视本地程序时,jconsole与本地程序必须使用相同的用户运行,或者使用root,比如要监视tomcat运行:

1
$ sudo -u tomcat7 jconsole <lvmid_for_tomcat>

如果出现如下错误提示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
No protocol specified
Exception in thread "main" java.lang.InternalError: Can't connect to X11 window server using ':0' as the value of the DISPLAY variable.
at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
at sun.awt.X11GraphicsEnvironment.access$200(X11GraphicsEnvironment.java:65)
at sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:110)
at java.security.AccessController.doPrivileged(Native Method)
at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:74)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:191)
at java.awt.GraphicsEnvironment.createGE(GraphicsEnvironment.java:102)
at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:81)
at sun.awt.X11.XToolkit.<clinit>(XToolkit.java:120)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:191)
at java.awt.Toolkit$2.run(Toolkit.java:869)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:861)
at javax.swing.UIManager.getSystemLookAndFeelClassName(UIManager.java:608)
at sun.tools.jconsole.JConsole.<clinit>(JConsole.java:60)

这是因为用户tomcat7没有被授权访问本地显示服务器造成的,执行以下命令然后重新运行jconsole即可:

1
2
$ xhost +local:all
non-network local connections being added to access control list

如果出现以下错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ sudo -u tomcat8 jconsole <lvmid_for_tomcat>
X11 connection rejected because of wrong authentication.
Exception in thread "main" java.awt.AWTError: Can't connect to X11 window server using 'localhost:0.0' as the value of the DISPLAY variable.
at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
at sun.awt.X11GraphicsEnvironment.access$200(X11GraphicsEnvironment.java:65)
at sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:115)
at java.security.AccessController.doPrivileged(Native Method)
at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:74)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at java.awt.GraphicsEnvironment.createGE(GraphicsEnvironment.java:103)
at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:82)
at sun.awt.X11.XToolkit.<clinit>(XToolkit.java:126)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at java.awt.Toolkit$2.run(Toolkit.java:860)
at java.awt.Toolkit$2.run(Toolkit.java:855)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:854)
at javax.swing.UIManager.getSystemLookAndFeelClassName(UIManager.java:611)
at sun.tools.jconsole.JConsole.<clinit>(JConsole.java:60)

是因为xauth授权的问题,因为tomcat8用户的主目录在/usr/share/tomcat8,但其主目录下并没有xauth授权文件.Xauthority文件,可以从登录用户的主目录下拷贝.Xauthority到tomcat8主目录,记得修改文件的属主和组为tomcat8,然后在重新执行命令就可以了。
注意:.Xauthority文件中的凭证会过期,每次登录其凭证都会更新。所以拷贝的办法只能临时用用,不能解决根本性的问题。

VisualVM

VisualVM是java的东家出品的、自由的性能分析和调优工具,基本上涵盖了以上几个命令行工具的功能。debian官方源里有对应的包VisualVM,也可以官网直接下载最新的zip包,解压缩后直接运行visualvm/bin/visualvm命令即可。这个工具更直观易用。

visualvm支持jmx和jstatd两种方式连接到远程jvm,jmx需要每jvm实例单独设置,而jstatd则可以连接系统范围内的所有jvm实例,无需单独设置。

jstatd配置
openjdk11内置jstatd,只要提供一个安全策略文件就可以直接运行,下面是一个可以运行的安全策略文件jstatd.all.policy

1
2
3
4
5
6
7
grant codebase "jrt:/jdk.jstatd" { 
permission java.security.AllPermission;
};

grant codebase "jrt:/jdk.internal.jvmstat" {
permission java.security.AllPermission;
};

运行jstatd,如果需要连接到所有的jvm实例,则需要使用特权用户运行,如果只需要连接到特定用户的jvm实例,可以用对应的用户来运行:

1
$ sudo jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=<ip_of_host> -J-Djava.rmi.server.logCalls=true

默认监听在1099端口,默认创建的RMI名字为JStatRemoteHost,最后一个选项为启用调用日志,可以不要。
jstatd连接并不支持cpu监视,所以如果需要cpu监视的话可以使用jmx远程连接或者本地连接(可以通过ssh X11Forward在jvm所在机器本地运行VisualVM)。

References:
[1]jstat用法详解
[2]jstatd(1)
[3]Starting jstatd in Java 9+
[4]jvisualvm connect to remote jstatd not showing applications
[5]VisualVM shows “Not supported for this JVM”

jenkins自动部署war到tomcat 7应用服务器时很不稳定,经常出现错误:

1
2
3
4
5
6
7
ERROR: Publisher hudson.plugins.deploy.DeployPublisher aborted due to exception
org.codehaus.cargo.container.ContainerException: Failed to deploy \[/var/lib/jenkins/jobs/devel_auto_build_deploy/workspace/build/libs/reis.war\]
...
Caused by: org.codehaus.cargo.container.tomcat.internal.TomcatManagerException: FAIL - Encountered exception javax.management.RuntimeErrorException: Error invoking method check
...
org.codehaus.cargo.container.tomcat.internal.TomcatManagerException: FAIL - Encountered exception javax.management.RuntimeErrorException: Error invoking method check
...

tomcat日志可以看到如下异常:
堆空间内存不足

1
java.lang.OutOfMemoryError: Java heap space

永久代内存不足

1
2
3
4
5
SEVERE: Exception invoking method check
java.lang.OutOfMemoryError: PermGen space
...
Exception in thread "http-bio-8080-exec-38" java.lang.OutOfMemoryError: PermGen space
OpenJDK 64-Bit Server VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGTERM to handler- the VM may need to be forcibly terminated

出现此问题的原因是tomcat默认配置的堆和非堆内存都太小了,需要调整如下JVM内存配置参数:

  • -Xms
    初始堆内存大小
  • -Xmx
    最大堆内存大,一般设置-Xms与-Xmx一样大小,根据应用类型和物理内存大小来决定二者的大小
  • -Xmn或者-XX:NewSize
    堆内存中年轻代的大小
  • -XX:PermSize
    永久代内存的初始大小
  • -XX:MaxPermSize
    永久代内存的最大值

一般设置这几个参数也就够了,debian系统上tomcat 7 设置JVM的内存参数要在配置文件/etc/default/tomcat7中的JAVA_OPTS参数中设置。

一个web app,服务器物理内存16G,其设置如下:

1
JAVA_OPTS="-Djava.awt.headless=true -Xmx5120m -Xms5120m -Xmn1024m -XX:PermSize=1024m -XX:MaxPermSize=1024m -XX:+UseConcMarkSweepGC"

References:
[1]JVM系列一:JVM内存组成及分配
[2]JVM系列三:JVM参数设置、分析
[3]java.lang.OutOfMemoryError: Permgen space

===
[erq]

mac os x上没有lsusb命令,可以使用如下命令列出系统usb设备信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
$ system_profiler SPUSBDataType
USB:

USB 3.0 SuperSpeed Bus:

Host Controller Location: Built-in USB
Host Controller Driver: AppleUSBXHCI
PCI Device ID: 0x9c31
PCI Revision ID: 0x0004
PCI Vendor ID: 0x8086
Bus Number: 0x0a

USB 3.0 Hi-Speed Bus:

Host Controller Location: Built-in USB
Host Controller Driver: AppleUSBXHCI
PCI Device ID: 0x9c31
PCI Revision ID: 0x0004
PCI Vendor ID: 0x8086
Bus Number: 0x0a

BRCM20702 Hub:

Product ID: 0x4500
Vendor ID: 0x0a5c (Broadcom Corp.)
Version: 1.00
Speed: Up to 12 Mb/sec
Manufacturer: Apple Inc.
Location ID: 0x14300000 / 1
Current Available (mA): 500
Current Required (mA): 94
Built-In: Yes

Bluetooth USB Host Controller:

Product ID: 0x828f
Vendor ID: 0x05ac (Apple Inc.)
Version: 0.99
Speed: Up to 12 Mb/sec
Manufacturer: Apple Inc.
Location ID: 0x14330000 / 4
Current Available (mA): 500
Current Required (mA): 0
Built-In: Yes

也可以用brew安装第三方lsusb命令:

1
2
3
4
5
6
7
8
$ brew update
$ brew tap jlhonora/lsusb
$ brew install lsusb
$ lsusb
Bus 020 Device 001: ID 0a5c:4500 Broadcom Corp. BRCM20702 Hub
Bus 020 Device 004: ID 05ac:828f Apple Inc. Bluetooth USB Host Controller
Bus 010 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 010 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

References:
[1]lsusb command for Mac OS X

===
[erq]