编辑/etc/libvirt/libvirtd.conf
listen_tls = 0
listen_tcp = 1
auth_tcp="none"
tcp_port = "16509"
即使设置了listen_tcp
也不会开启监听服务, 重启libvirt-bin
服务,验证:
sudo netstat -nlpt
# 可见16509端口并没有开启
ps aux | grep libvirt
# 可见libvirtd没有-l参数
需要开启监听服务,设置/etc/init/libvirt-bin.conf
文件,设置exec /usr/sbin/libvirtd $libvirtd_opts -l
,注意后面的-l
选项 不能直接写在libvirtd_opts
上,不生晓,原因不明
重启libvirt-bin
服务, 使用netstat
是否开启了tcp端口和ps
查看libvirtd是否有-l
选项,都没有问题后,运行:
virsh --connect qemu+tcp://node1/system list
其中node1
为主机名,如果无错误,则表示正常开启tcp监听服务.
An easy jekyllclient to manager your posts in your local host.
That's easy to use once you configure it :) !
All the configure items are in the conf/blog.conf and it easy to configure ! If you change the location of this config file, you need to set JEKYLL_CONF
environment variable as follows:
export JEKYLL_CONF=path/to/yourconf
All your config items should be in site section as follows:
[site]
base = <the root path of your blog>
posts = <the posts path, default '_posts'>
username = <your usename>
Once you finish the work above, Let's go!
Don't know how to work ? Run './blog help' to show help messages:
usage: blog [--version] [--debug] <subcommand> ...
A shell to manager blog
positional arguments:
<subcommand>
create Create a new post.
delete Delete specified post.
list List all the posts.
ls Equivalent to list.
show Read a Post
bash-completion
help Display help about this program or one of its subcomands.
optional arguments:
--version show program's version number and exit
--debug Print debugging output
See "blog help COMMAND" for help on a specific command.
Just as shown above, you can run blog help COMMAND
for help on a specific command.
Want to list all your posts ? Just run ./blog list
:
+-------------------------------+----------+------------+
| title | filetype | date |
+-------------------------------+----------+------------+
| scriptnote | markdown | 2015-04-26 |
| HowToInstallJekyll | markdown | 2015-04-26 |
| java-concurrency | markdown | 2014-09-20 |
+-------------------------------+----------+------------+
A Pretty table ? Thanks to python prettytab
.
If you want to show more details on the posts, run ./blog list -d
:
+---------------------------------+------------+----------+--------+------------------------------+----------+----------+
| title | date | category | layout | tags | filetype | comments |
+---------------------------------+------------+----------+--------+------------------------------+----------+----------+
| HelloWorld1 | 2015-03-18 | linux | post | bash | markdown | true |
| HelloWrold2 | 2014-11-30 | linux | post | c | markdown | true |
+---------------------------------+------------+----------+--------+------------------------------+----------+----------+
You'd like to show the contend of specified post ? Just run ./blog show -t HelloWorld1
.
You can also set your style to read the post, choice from cat, less, more
styles.
Once you get a new fresh idea and want to write down to your blog, run blog create
, this smart script will set your metedata automatically, and call your editor depend on your EDITOR environment
Let's record our life by jekyll from now!
Yes, welcome!
OpenStack是一个云平台管理的项目,由几个主要的组件组合起来,旨在为公共及私有云的建设与管理提供平台。它是由 Rackspace 和 NASA 共同开发的云计算平台,帮助服务商和企业内部实现类似于 Amazon EC2 和 S3 的云基础架构服务(Infrastructure as a Service, IaaS),具体查看openstack官网
这个项目旨在写一个方便调用、方便扩展的openstack开发包。它是根据openstack api封装的java开发库,最初应实验室需求而开发。目前已经花了陆陆续续近3个月的时间,仅仅实现了基本功能,还有很多bug,以及功能尚未实现。
项目地址:https://github.com/krystism/openstack-java-sdk
首先使用maven构建本项目:
mvn package
如果需要把依赖包一块打进一个整体包,使用一下命令:
mvn assembly:assembly
项目运行需要配置文件,配置文件路径由系统变量OPENSTACK_CONF_PATH
指定,默认为/etc/openstack
,参考配置文件说明 我学习了openstack官方python库的设计架构,尽力做到调用简单,方便.以下是demo:
OpenstackSession session = OpenstackSession.getSession("username", "password");// get session
Nova nova = session.getNovaClient(); // get nova client
// get a flavor list, print their name
for (Flavor flavor : nova.flavors.list()) {
System.out.println(flavor.getName());
}
// create a new server
Server server = new Server();
server.setName("demo");
server.setImageRef("imageId");
server.setFlavorRef("flavorId");
// some other config
nova.servers.create(server); // call create method to execute.
由于时间有限,加上本人代码功底尚浅,需要完美完成所有功能实在是感觉力不从心。希望有更多的大牛能够加入一起完成,并且指出我目前工作的不足,甚至重构整个代码,我真诚的感谢每一位热心的朋友!
下面讲讲我目前如何扩展新功能:
model就是实体对应的java bean,接收请求过来的数据一般是json,即要把json表示的对象转化成的java对象。你可以完全由自己来定义自己的bean,我的所有bean都继承AbstractEntity,属性由Property注解,构造方法传递一个JSONObject对象,一般直接调用基类的构造方法就能完成JSONObject到java bean的转化。以下是model demo:
@Entity("volume_type")
public class VolumeType extends AbstractEntity {
private static final long serialVersionUID = -6539238104579991330L;
@Property("extra_specs")
private JSONObject metadata;
/*
@Property("name")
private String name;
@Property("id")
private String id;
*/
public VolumeType() {
super();
}
public VolumeType(JSONObject jsonObj) {
super(jsonObj);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// some other getter and setter here
}
管理接口即对bean定义操作,这些操作可能根据api的版本不同有不同的实现。在设计接口时,我没有使用共同接口,也尚未使用接口继承,原因是很多实体bean对应的操作差异性很大,即使是相同的操作,参数也不完全相同。下面是一个管理接口demo:
public interface ServerManager {
/**
* Get a server.
* @param id ID of the Server to get.
* @return Server
* @throws OperationException
*/
Server get(String id) throws OperationException;
/**
* Get a list of servers.
* @return List of server
* @throws OperationException
*/
List<Server> list() throws OperationException;
/**
* Stop(power off) the server
* @param id The id of server to stop.
* @throws OperationException
*/
void stop(String id) throws OperationException;
/**
* Start(power on) the server,
* @param id The id of server to start.
* @throws OperationException
*/
void start(String id) throws OperationException;
/**
* Reboot a server, for a software-lever reboot
* @param id The ID of server to reboot.
* @see reboot(String id, boolean hard)
*/
void reboot(String id) throws OperationException;
/**
* update the name for a Server
* @param id the id of server to rename
* @param name the new name of the server.
* @throws OperationException
*/
void rename(String id, String name) throws OperationException;
/**
* Create (boot) a new Server.<br/>
* <i>Remember</i> : You must set name, imageRef, flavorRef !
* @param instance The new server you have created.
* @return
* @throws OperationException
*/
Server create(Server instance) throws OperationException;
/**
* Delete (i.e shut down and delete the image) this server.
* @param id The ID of server to delete.
* @throws OperationException
*/
void delete(String id) throws OperationException;
}
接下来就是具体实现接口,可能会根据api版本不同而有不同的实现,实际应用时可以根据配置文件指定需要使用的版本。下面是一个实现Demo:
public class Flavors extends AbstractManager<Flavor> implements FlavorManager{
private final String PREFIX = "/flavors";
public Flavors(Authenticated credentical) {
super(credentical, Flavor.class);
}
/**
* Get a list of all flavors
* @return A List , which holds flavors
* @throws OperationException
*/
@Override
public List<Flavor> list() throws OperationException {
return _list(PREFIX + "/detail");
}
/**
* Get a specific Flavor.
* @param id The ID of Flavor to get.
* @return Flavor
* @throws OperationException
*/
@Override
public Flavor get(String id) throws OperationException {
return _get(PREFIX + "/" + id);
}
/**
* Delete a specific Flavor.
* @param id The ID of Flavor to delete.
* @throws OperationException
*/
@Override
public void delete(String id) throws OperationException {
_delete("/flavors/" + id);
}
/**
* create a new flavor for a tenant
* @param flavor The flavor to create
* @return The new flavor
* @throws OperationException
*/
@Override
public Flavor create(Flavor flavor) throws OperationException {
return _create("/flavors", flavor);
}
}
注册新功能就是把相应的管理接口添加到client下(比如Nova, Glance等),目前我直接硬编码,实际操作应该根据配置文件选择api版本由工厂负责创建,以下是demo:
public class Nova {
public final FlavorManager flavors;
public final HypervisorManager hypervisors;
public final ServerManager servers;
public final KeyPairManager keypairs;
public Nova(Authenticated credentical) {
// bad work, don't do that!!
flavors = new Flavors(credentical);
hypervisors = new Hypervisors(credentical);
servers = new Servers(credentical);
keypairs = new KeyPairs(credentical);
}
如何为已经实现的接口增加新功能,比如在请求前记录日志,或者使用cache。只需要增加装饰器即可!以下是Demo:
public class FlavorCachedManager implements FlavorManager {
private FlavorManager flavors;
public FlavorCachedManager(FlavorManager flavors) {
this.flavors = flavors;
}
@Override
public Flavor get(String id) throws OperationException {
Flavor flavor = getFromCache(id);
if (flavor == null) {
flavor = flavors.get(id);
}
addToCache(flavor);
return flavor;
}
}
The MIT License (MIT)
什么是蓄水池抽样,它能解决什么问题?
百度面试以算法为主啊,手动写代码。第一道题是实现c语言库函数strcpy,这个原理很简单,但要注意以下这几点:
第二道题是写一个类,实现堆的操作。说实话,虽然堆的操作不难,但要真正实现它并不容易。以下需要注意的点:
重点是第三道题目:给定一个文件,从中随机取出n行,并计算时间复杂度。我上来便是这样的代码:
import random
def sample(filename, n = 3):
assert(filename is not None)
result = []
with open(filename) as f:
lines = f.readlines()
while len(result) < n :
line = random.choice(lines)
if line not in result:
result.append(line.strip())
return result
这种方法
后来面试官问我知不知道分治法,我说了解,但这有关系么?文件分割建索引?全错!!!
蓄水池抽样(Reservoir Sampling )是一个很有趣的问题,它能够在o(n)时间内对n个数据进行等概率随机抽取, 例如:从1000个数据中等概率随机抽取出100个。另外,如果数据集合的量特别大或者还在增长(相当于未知数据集合总量), 该算法依然可以等概率抽样。
以上摘自handspeaker博客
算法步骤为:
利用归纳法可以证明每行被取的概率是相等的,证明过程 见handspeaker博客
问题解决了,毫无悬念!
import random
def sample(filename, n = 5):
assert(filename is not None)
result = []
with open(filename, mode = "r") as f:
for i in range(n):
line = f.readline()
if line == '':
return result
else:
result.append(line.strip())
i = n
for line in f:
k = random.randint(0, i)
if k < n:
result[k] = line.strip()
i += 1
return result
康托展开是一个全排列到一个自然数的双射,常用于构建hash表时的空间压缩。
公式为:
X = a[n - 1] * (n - 1)! + a[n - 2] * (n - 2)! + ... + a[0] * 0!,
其中, a[i]为整数,并且0 <= a[i] <= i, 0 <= i < n, 表示当前未出现的的元素
中排第几个。
比如31254,
因此a数组序列为2 0 0 1 0
X = 2 * 4! + 0 * 3! + 0 * 2! + 1 * 1! + 0 * 0!
= 2 * 24 + 1
= 49
既然是双射关系那一定可以反推出来31254这个序列。 首先我们需要推出a序列。
再由a数组推出序列,根据a数组的意义反推。
因此序列为3 1 2 5 4
一个直观的应用就是给定一个自然数集合和一个序列,求这个序列中按从小到大的顺序 排第几个?
比如1 2 3 4 5, 3 1 2 5 4比它小的序列有49个,即它排第50
另一个应用就是逆推第K个排列是多少,比如第50个全排列是多少?则首先减1得到49, 再反推即可得到3 1 2 5 4
另外在保存一个序列,我们可能需要开一个数组,如果能够把它映射成一个自然数, 则只需要保存一个整数,大大压缩空间.
计算包括编码(根据序列求对应的自然数)和解码(康托展开)。
static const int FAC[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
int cantor(int *a, int n)
{
assert(n < 10);
int x = 0;
for (int i = 0; i < n; ++i) {
int smaller = 0;
for (int j = i + 1; j < n; ++j) {
if (a[j] < a[i])
smaller++;
}
x += FAC[n - i - 1] * smaller;
}
return x;
}
int decantor(int *a, int n, int k)
{
int *num = malloc(sizeof(int) * n );
int len = n;
for (int i = 0; i < n; ++i)
num[i] = i + 1;
int cur = 0;
for (int i = n - 1; i > 0; --i) {
int index = k / FAC[i];
k %= FAC[i];
a[cur++] = num[index];
listRemove(num, &len, index);
}
a[cur] = num[0];
free(num);
return 0;
}
当做虚拟机备份快照时,镜像的大小一般会大于实际数据大小,you'll need to zero out all free space of the partitions contained within the guest first.
参考维基百科:https://pve.proxmox.com/wiki/Shrin_Qcow2_Disk_Files
针对linux镜像:
尽量删除一些无用文件
dd if=/dev/zero of=/mytempfile
# that could take a some time
rm -f /mytempfile
mv image.qcow2 image.qcow2_backup
qemu-img convert -O qcow2 image.qcow2_backup image.qcow2
qemu-img convert -O qcow2 -c image.qcow2_backup image.qcow2
nc命令可用于发送任务tcp/udp连接和监听.
官方描述的主要功能包括:
下面看看官方的几个例子:
在A机器运行(假设A机器主机名为node1
:
nc -l 1234 # -l表示监听
在B机器运行:
nc node1 1234
此时从A或者B机器输入任何信息,都会在对方的机器中回显,实现了简单的即时聊天工具.
假设B机器有一个文件data.txt,需要传输到A机器:
在A机器:
nc -l 1234 >data.txt # data.txt需要保存的目标文件名
在B机器:
nc node1 1234 <data.txt # data.txt需要传输的文件
假设B需要远程操作A,又没有安装ssh:
在A机器:
rm -f /tmp/f; mkfifo /tmp/f
cat /tmp/f | /bin/sh -i 2>&1 | nc -l 127.0.0.1 1234 > /tmp/f
在B机器:
nc node1 1234
echo "GET / HTTP/1.0\r\n\r\n" | nc localhost 80
# 查看主机名为node1的80端口是否开放
nc -zv node1 80
# 扫描主机名为node1的1~1024哪些端口是开放的
nc -zc node1 1-1024
sed -e ':a;N;s/\n//;s/ //g;ba' test.txt
or
cat test.txt | tr -d '\n '
xargs -0
或者 --null
表示分隔符为0
字符, -n
表示每次传参数的最大个数
cat /proc/$$/environ | xargs -0 -n 1
cat /proc/$$/environ | tr '\0' '\n'
export LD_LIBRARY_PATH=/opt/myapp/lib
支持 ++
--
+
-
*
/
**
&
|
等
a=$((5 ** 5)) # a = 3125, 等价a = let 5 ** 5
echo "scale=3; 10 / 3" | bc # 浮点数
[[ 'a5a' =~ [a-zA-Z][0-9][a-z] ]] && echo "YES" || echo "NO"
# 注意 =~ 后面的正则表达式不能用引号
>&
实际复制了文件描述符, ls >dirlist 2>&1
与 ls 2>&1 >dirlist
不一样
declare -a a
把变量a声明为索引数组declare -A a
把变量a声明为关联数组${a[@]}
获取所有的值, ${!a[@]}
获取所有的键 ### 7. exec & source\(command1;command2\)\
: 将命令置于新进程,继承父进程所有文件描述符
declare -A map
map[key]=value
map=([key1]=value1 [key2]=value2)
keyset: ${!map[@]}
values: ${map[@]}
map[count]=0
let map[count]++
out="$(ls)"
IFS
IFS=','
line='1,2,3,4,5'
for i in line
do
echo $i
done
# 迭代
for i in list
do
echo $i
done
# range
for i in {1..50}
do
echo $i
done
# c 风格
for((i = 0; i <= 50; ++i))
do
echo $i
done
cat - a >out # 从标准输入流输入内容插入a中
cat -s 过滤多余空行
#删除所有的swp文件
find . -maxdepth 1 -type f -name "*.swp" -delete
# 将10天前的文件复制到OLD目录
find . -maxdepth 1 -type -f -mtime +10 -name ".txt" -exec cp {} OLD \;
echo -n "split:split:split:split" | xargs -d : -n 2
split split
split split
#output
split split
split split
# 统计c代码行数
find . -maxdepth 1 -type f -name ".c" -print0 | xargs -0 wc -l
# 注意print0 和-0 表示以null作为分隔符,防止文件名包括空格回车造成错误
# 小写转化大写
echo "heLLo" | tr 'a-z' 'A-Z'
echo "heLLo" | tr '[:lower:]' ''[:upper:]'
# 空格转化为回车
echo "1 2 3 4" | tr ' ' '\n'
# 删除数字
echo "abcd123dd" | tr -d '0-9' # abcddd
# 保留数字
echo "abcd123dd" | tr -d -c '0-9' # 123
# 压缩字符
echo "aaabbbccc" | tr -s 'ab' # abccc
# 求和
echo '1 2 3 4 5' | echo $[ $(tr ' ' '+') ]
# 产生校验
md5sum test.txt >test.md5
# 校验
md5sum -c test.md5
# 默认按字典序排列
echo "3 2 1 13 11 12" |tr ' ' '\n' | sort | tr '\n' ' ' # 1 11 12 13 2 3
# 使用-n按大小排序
echo "3 2 1 13 11 12" |tr ' ' '\n' | sort -n | tr '\n' ' ' # 1 2 3 11 12 13
# 使用-r表示逆序
# 检查文件是否排序
sort -C test1 && echo "sorted" || echo "unsorted"
# 使用-k指定哪个列作为键
# -b 忽略前导空白行
# -m 把已排好序的文件归并
# 注意该文件必须保证是已排好序的文件
# 过滤重复行
echo "1 2 2 3 3 3" | tr ' ' '\n' | uniq # 1 2 3
# 只输出唯一行
echo "1 2 2 3 3 3" | tr ' ' '\n' | uniq -u # 1
# 统计重复次数
echo "a b b c c c c" | tr ' ' '\n' | uniq -c # 1 a 2 b 4 c
# 输出重复行
echo "a b b c c c c" | tr ' ' '\n' | uniq -d # b c
# 获取文件扩展名
${file#*.}
# 或者文件名
${file%.*}
# 把*.JPG 重命名为*.jpg
rename *.JPG *.jpg
# 将文件名的空格替换为_
rename 's/ /_/g' *
# 转化文件大小写
rename 'y/a-z/A-Z/' *
a=() # 声明一个空数组
a+=(1 2) # 追加1 2 到数组a中
PIDS=()
for i in {1..50}
do
echo $i >>out &
PIDS+=("$!") # $!表示最后一个后台进程pid,追加到PIDS数组中
done
wait ${PIDS[@]}
# 两个文件必须是排好序的
comm A.txt b.txt
# 第1列包含只在A文件(A的差集),2列包含只在B文件(B 的差集),
# 第3列包含A、B相同的行(A、B的交集)
# -1 -2 -3 分布表示删除第1,2,3列
# 查看文件差异
diff a.txt b.txt
# 打补丁
diff a.txt b.txt >patch
patch a.txt < patch
# 取消补丁
patch -p1 a.txt <patch
# 生成目录
diff -Naur d1 d2
# -r 递归 -N:缺失文件视为空文件 -u:生成一体化输出 -a 将所有文件视为文本文件
head -n num
# num 为正数,则只输出前num行,默认为10,若num为负数,则输出前num行以外的行
tail -n num
tail -f file
#当进程PID停止,tail自动退出
tail -f --pid $PID file
ls -d */ # 不能少/
ls -F | grep "/$"
ls -l | grep "^d"
find . -maxdepth 1 -type d -print
# -o 只输出匹配的文本部分
# -c 统计匹配行数(不是次数)
# 求匹配次数
grep -o '[0-9]+' | wc -l
# 打印行号 -n
# -b打印偏移量,常常和-o连用
# -l 只打印匹配的文件列表,-L打印不匹配的文件列表
# -R 递归
# -i 忽略大小写
# 匹配多个样式, -e
grep -e 'pattern1' -e 'pattern2'
# 指定文件
# 只搜索c或者cpp文件
grep --include *.{c,cpp}
# --exclude "README.md" 不搜索该文件
# -Z 输出以0作为文件名终结符,与-l结合使用
grep -Zlr "test" *
# -q 不输出任何东西,匹配返回0,不匹配返回1
# -A -B -C 输出上下文-A向后输出n行,-B向前输出n行,-C 向前向后输出n行
# -f 指定列, 与--complement结合,输出不包括这些列的所有列 -f 3,5打印第3,5列
# -f 3- 打印从第3列开始的所有列
# -c字符 -b字节 -f字段
# -v 传递外部变量
# getline读取一行,尤其在BEGIN块使用过滤头部信息
# getline var,var保存内容,若调用不带参数的getline,则可以使用$0-$9访问
# -F列分隔符
bash支持两种数组,一种是索引数组,一种是关联数组
数组的值类型是任意的,索引也未必一定要连续,当做列表理解更好
下面总结下索引数组,即列表:
declare -a a
a=(1 2 3 4)
# OR
a=([0]=2 [3]=8) # 注意长度为2,不是4
size=${a[@]}
a+=(11 12 13 14)
a[1]=9
value=${a[0]} # 读取索引0的值
unset a[0]
unset a
echo ${a[@]:1:3} # 从索引1开始的3个元素
# 也支持负数索引,-1表示最后一个,但负数必须用括号括住
last=${a[@]:(-1):1}
for i in ${a[@]}
do
echo $i
done
declare -A map
map[key1]=value1
map[key2]=value2
# or
map=([key1]=value1 [key2]=value2)
size=${!map[@]}
keyset=${!map[@]}
values=${map[@]}
for key in ${!map[$@]}
do
echo $key:${map[$key]}
done