编辑/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