openSUSE 12.1 配置工作环境[1]

作者:Ajian 发布时间:March 28, 2012 分类:openSUSE

     我使用openSUSE已经有快5年了 ,对于他也是情有独钟,满足了我对炫丽桌面的需求,也可以很稳定的提供使用环境,虽然中间也经历了很多版本的变化和无数的折腾,但总体还是很不错的,中间因为openSUSE的版本对我的笔记本无线网卡不支持 用了大半年的Ubuntu 相对来说Ubuntu很是活跃而且社区支持和文档都比较多,但我本人不是太喜欢Gnome 还有debian系统的结构也不是很习惯 最主要是受不了每天大量的软件更新,经常还会更新之后出现想不到的bug。openSUSE 他的管理界面和结构都比较清晰 而且跟我管理的服务器的结构没有太大的差异 使用还是比较方便。这次我主要介绍下openSUSE 12.1 配置我的工作环境的细节 ,算是一个check list 。现在基本上拿任何一台电脑都可以很方便的同步我的工作环境 ,而且也符合我自己的工作习惯,读者可以当成一种借鉴。

安装openSUSE 12.1之后 ,我主要是习惯了使用root 所以很多配置都是需要修改的。安装的时候不要建立其它账号 直接设置root密码就可以了。(虽然直接使用root不是好的习惯 但至今还没有做过一件错事 当然你就不要学我了 哈哈) 接下来按顺序配置openSUSE


配置源:

 

Add Software Repositories

zypper ar http://mirrors.magnetjoychina.com/opensuse/distribution/12.1/repo/non-oss/ magnetjoy_opensuse12.1_non-oss
zypper ar http://mirrors.magnetjoychina.com/opensuse/distribution/12.1/repo/oss/ magnetjoy_opensuse12.1_oss
zypper ar http://mirrors.magnetjoychina.com/opensuse/update/12.1/ magnetjoy_opensuse12.1_update

我使用的是公司自己做的mirror mirror会在半夜进行同步 白天就可以很快的进行更新 如果想使用国内比较快的源可以将 magnetjoychina 替换成 sohu就可以了。

还要打开yast -> Software Repositories  去掉默认的update oss non-oss 和光盘安装时候的cd 源

进行zypper up

安装Dropbox :

安装dropbox 主要是因为 我保存了很多东西在dropbox里面,这个是我的一个核心文档,dropbox除了有各个项目的文档 还有我的工作环境 操作系统的各种配置文件 如:repositories vim配置文件 bashrc .bash_profile kopete日志 RSS文档 等等 只有了这些我才可以很快的时行配置,甚至我可以写一个自动的脚本 就可以很方便的复制工作环境了。

安装脚本kde-dropbox.sh:

#!/bin/bash
test -d /usr/lib64 && myarch="x86_64" || myarch="x86"
echo "Install dropbox (arch: $myarch) without nautilus in KDE4"
echo "Please make sure you have a dropbox account!"
echo "Continue ? (y or n)"
read yn
if [ $yn == "y" ]; then
echo "Installing ..."
#wget -N -O dropbox-$myarch.tar.gz http://www.dropbox.com/download/?plat=lnx.$myarch
tar -zxof dropbox-$myarch.tar.gz
mv .dropbox-dist ~
echo "Do you want to startup Dropbox automatically when login? (y or n)"
read autoyn
if [ $autoyn == "y" ]; then
ln -s ~/.dropbox-dist/dropboxd ~/.kde4/Autostart/
fi
echo "Do you want to add Dropbox startup to your menu? (y or n)"
read menuyn
if [ $menuyn == "y" ]; then
echo "Icon=$HOME/.dropbox-dist/dropbox.png" >> dropbox.desktop
echo "Exec=$HOME/.dropbox-dist/dropbox start -i" >> dropbox.desktop
mkdir -p ~/.local/share/applications
mv dropbox.desktop ~/.local/share/applications/
mv dropbox.png ~/.dropbox-dist/
fi
echo "Starting setup ..."
~/.dropbox-dist/dropboxd &
echo "Done!"
fi

注意 因为在国内dropbox会有被阻止,所以我一般都是将脚本中的wget那句注释,想办下载dropbox-$myarch.tar.gz之后 再执行脚本 就可以方便的进行安装 并且自启动。

安装dropbox后,输入账号和密码 同步内容到本地。

添加额外的源:

可以编辑一个自己的repo文件如:myrepo.repo 存放到/etc/zypper/repos.d

[download.videolan.org-SuSE]
name=VideoLan Repository
enabled=0
autorefresh=0
baseurl=http://download.videolan.org/pub/videolan/vlc/SuSE/12.1/
path=/
type=rpm-md
keeppackages=0
[Packman Repository]
name=Packman Repository
enabled=1
autorefresh=0
baseurl=http://packman.inode.at/suse/openSUSE_12.1/
type=rpm-md
keeppackages=0
[subpixel]
name=subpixel
enabled=1
autorefresh=0
baseurl=http://opensuse-community.org/subpixel/openSUSE_12.1
path=/
type=rpm-md
keeppackages=0
[swyear]
name=swyear
enabled=1
autorefresh=1
baseurl=http://download.opensuse.org/repositories/home:/swyear/openSUSE_12.1
path=/
type=rpm-md
keeppackages=0
[home:swyear:shutter]
name=home:swyear:shutter
enabled=1
autorefresh=1
baseurl=http://download.opensuse.org/repositories/home:/swyear:/shutter/openSUSE_12.1/
type=rpm-md
keeppackages=0

 

安装常用软件:

有一些常用的必要软件,可以在一开始就进行安装。

 

install need software
zypper in ibus mplayer smplayer umplayer radiotray shutter per-Proc-Simple w32codec-all libxine1-codec stardict dia kdesvn subversion git vim-enhanced virtualbox opera chromium

ibus 输入法 

mplayer相关的播放器

w32codec-all libxine1-codec 编码 有它们才可以播放不同的视频

stardict 本地字典

dia 类似visio可以方便的创建自己的拓扑图

radiotray 收音机 还需要安装一些其它的软件gstream相关的

shutter 一个很好的截图和编程软件 ksnapshot 虽然可以很方便的截图 但是没有编辑

virtualbox 虚拟机

opera 浏览器

chromium chrome google的浏览器

subversion svn版本控制管理 现在在用的

git git版本管理工具 将要使用的

 

Shutter安装:

一键安装:http://software.opensuse.org/ymp/home:swyear/openSUSE_12.1/shutter.ymp

因为要写这篇文章所以 首先要有一个截图工具 shutter就排在了安装首位 我是按我的安装顺序来记录的。

如果在安装shutter的时候需要perl的依赖问题 可以添加一些perl的 源

[devel:languages:perl]
name=devel:languages:perl
enabled=1
autorefresh=1
baseurl=http://download.opensuse.org/repositories/devel:/languages:/perl/openSUSE_12.1/
type=rpm-md
keeppackages=0

我遇到一个问题:

linux-htd5:~/Dropbox/my # shutter
Failed to open file '/usr/share/shutter/resources/icons/sel_window_tooltip.svg': No such file or directory at /usr/share/shutter/resources/modules/Shutter/App/Menu.pm line 533, <DATA> line 19.


安装完后就没有这个文件,但是就是要这个文件才可以打开 简单的给他一个空名字也可以

linux-htd5:/usr/share/shutter/resources/icons # cp sel_window.svg sel_window_tooltip.svg


修改KDE界面和字体:

修改KDE界面 其实集成得已经相当不错了。全部都可以在 Configure Desktop 里面搞定。

修改字体: Configure Desktop - > Application Appearance ->Fonts 设置DPI 和 anti-aliasing 选择自己喜欢的字体和大小

当然也可以自己安装雅黑 Linux安装微软雅黑字体

还可以在swyear 的源里面安装有关ttf的包 如chinese-font 符合汉字相关的一些字体

snapshot2.png

配置命令快捷方式:

使用alt+F2可以很方便的 调用出想要的命令和软件甚至是文档 ,不过我不喜欢默认的样式 可以通过设置 实现如下的界面

snapshot4.png

配置默认的session:

默认openSUSE 启动都会将上次关闭的应用全部打开,还是重启登陆之后有一个干净的界面会比较喜欢。

Configure Desktop -> Startup and Shutdown  ->  Session Management选择 start with empty session

Selection_009.png

在autostart 可以设置自启动的相关脚本 Service Manager 可以关闭不需要的自启动服务 如apper  这个自动的更新服务很是麻烦 

(今天就写到这 明天继续... )

 

Golang : TCP Chat Server and Client 聊天服务程序

作者:Ajian 发布时间:March 27, 2012 分类:Golang

最近在学习Go,如果有C语言功底是很容易接触go语言的,但是我是一个运维之前写的大部分程序都是面向过程的shell python脚本类型语言,对c也不是太熟悉,所以接触Go还是有些吃力的,尤其是涉及网络传输,channel ,指针,结构等术语的时候,再加上GO的中文教程和demo都比较少,还有相当的晕。我还是使用我的学习方法,用一个实际需求例子来一学习,当然首先还是要过一遍GO发布的基础教学的。

ps:使用的是r60的版本编译的,后来发现Go1的有很多变化,以后相关的go程序还是要标示出当时的版本

需求:使用TCP协议写一个多人同时在线聊天服务,包括服务端和客户端

参考网站:

Golang Away: TCP Chat Server //基本能用 server端但我进行了一些小的修改和优化 去了些多余的东西

simpler chat server and client in golang //基本不能用 client 有很多的语法错误 不过可以一步步排查

Server:

package main                                                                                              
//这个是必需的 独立运行的执行文件必需使用                                                                 
import "fmt"
import "net"
import "container/list"
import "bytes"
//加载其它的库                                                                                            
//fmt 实现格式化的I/O 类似printf                                                                         
//net 实现网络协议TCP UDP 在这里使用TCP                                                                   
//container/list 实现双向链表队列                                                                         
//bytes 字符数组操作相关功能                                                                              
                                                                                                          
type Client struct {                                                                                      
    //定义一个结构 struct 用于抽象数据类型                                                                
    Name string                                                                                           
    Incoming chan string                                                                                  
    Outgoing chan string                                                                                  
    Conn net.Conn                                                                                         
    Quit chan bool
    ClientList *list.List
}

//go可以返回多个值  使用括号()
func (c *Client) Read(buffer []byte) (int, bool) {
    bytesRead,error := c.Conn.Read(buffer)
    //:= 同时定义和赋值,并且可以同时多个变量
    if error != nil {
        //nil is like C's NULL
        c.Close()
        Log(error)
        return 0, false
        //返回的值为bool类型
    }
    Log("Read ",bytesRead," bytes")
    return bytesRead, true
}

func (c *Client) Close(){
    c.Quit <- true
    //管道传递true给Quit
    c.Conn.Close()
    c.RemoveMe()
    //调用RemoveMe func
}

//Equal 帮助对比client
func (c *Client) Equal(other *Client) bool{
    if bytes.Equal([]byte(c.Name),[]byte(other.Name)){
        if c.Conn == other.Conn{
            return true
        }
    }
    return false
}

func (c *Client) RemoveMe(){
    for entry := c.ClientList.Front();entry != nil ; entry = entry.Next(){
        //双向链表队列的使用
       client := entry.Value.(Client)
       if c.Equal(&client){
            Log("RemoveMe: ",c.Name)
            c.ClientList.Remove(entry)
       }
    }
}

//...可变数组 在屏幕输出日志
//interface 代表任意数据类型 Everything in Go is derived from interface, so in theory, this can be any datatype.
func Log(v... interface{}){
    fmt.Println(v...)
}

func IOHandler(Incoming <- chan string,clientList *list.List){
    for {
        //在go里面没有while do ,for可以无限循环
        Log("IOHandler: Waiting for input")
        input := <- Incoming 
        Log("IOHandler: Handling ",input)
        for e := clientList.Front(); e != nil; e= e.Next(){
            client := e.Value.(Client)
            client.Incoming <-input
        }
    }
}

func ClientReader(client *Client){
    //make创建切片slice 长度2048 http://golang.org/doc/effective_go.html#allocation_make
    buffer :=make([]byte,2048)
    for {
        n, status := client.Read(buffer)
        if !status {
            break
        }

        if bytes.Equal(buffer,[]byte("/quit")){
            client.Close()
            break
        }
        Log("ClientReader received ",client.Name,"> ",string(buffer[:n]))
        send := client.Name+"> "+string(buffer[:n])
        client.Outgoing <- send
    }
    client.Outgoing <- client.Name + " has left chat"
    Log("ClientReader stopped for ", client.Name)
}

func ClientSender(client *Client){
    for {
        select {
            //select http://golang.org/doc/go_spec.html#Select_statements
        case buffer := <-client.Incoming:
            Log("ClientSender sending ",string(buffer), " to ",client.Name)
            client.Conn.Write([]byte(buffer))
        case <- client.Quit:
            Log("Client ",client.Name," quitting")
            client.Conn.Close()
            break
        }
    }
}

//该函数主要是接受新的连接和注册用户在client list
func ClientHandler(conn net.Conn,ch chan string,clientList *list.List){
        buffer := make([]byte,1024)
        bytesRead,error := conn.Read(buffer)
        if error != nil{
                Log("Client connection error: ",error)
        return
        }
        name := string(buffer[0:bytesRead])
//      newClient := &Client{name,make(chan string),ch,conn,make(chan bool),clientList}
//      初始化struct赋值的两种方法
        newClient := &Client{
        Name :name,
        Incoming : make(chan string),
        Outgoing : ch,
        Conn : conn,
        Quit : make(chan bool),
        ClientList : clientList,
    }
    //创建go的线程 使用Goroutine
        go ClientSender(newClient)
        go ClientReader(newClient)
        clientList.PushBack(*newClient)
        ch <-string(name + " has joined the chat ")
}

func main(){
        Log("Hello Server!")
        clientList := list.New()
    in := make (chan string)
    //创建一个管道 chan map 需要make creates slices, maps, and channels only
    go IOHandler(in,clientList)
    netListen,error := net.Listen("tcp",":9988")
    if error != nil {
        Log(error)
    }else{
        //defer函数退出时执行
        defer netListen.Close()
        for {
            Log("Waiting for clients")
            connection,error := netListen.Accept()
            if error != nil {
                Log("Client error: ",error)
            }else{
                go ClientHandler(connection,in,clientList)
            }
        }
    }
}

 

基本上使用这个服务,可以使用telnet IP 9988  多人进行聊天使用了

 

telnet 127.0.0.1 9988
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Name1
Name1
 has joined the chat 
Name1
> 
Jim
 has joined the chat Jim                                                                                  
>                                                                                                         
Jim                                                                                                       
> Hi!                                                                                                     
Jim                                                                                                       
> Nice to meeting you !                                                                                   
me Too                                                                                                    
Name1                                                                                                     
> me Too                                                                                                  
         

 

Client:

 

package main

import (
    "fmt";
    "net";
//    "log";
    "os";
    "bufio";
//    "strings";
    "time";
    "flag";
)

var running bool;  // global variable if client is running

var debug = flag.Bool("d", false, "set the debug modus( print informations )")

// func Log(v ...): loging. give log information if debug is true
//func Log(v ...) {
//    if *debug == true {
//        ret := fmt.Sprint(v);
//        log.Stdoutf("CLIENT: %s", ret);
//    }
//}
func Log(v ...interface{}){
        fmt.Println(v...)
}


// func test(): testing for error
func test(err os.Error, mesg string) {
    if err!=nil {
        Log("CLIENT: ERROR: ", mesg);
         os.Exit(-1);
    } else {
        Log("Ok: ", mesg);

    }
}

// read from connection and return true if ok
func readabc(con net.Conn) string{
    //var buf [4048]byte;
    buf := make([]byte,4096)
    _, err := con.Read(buf);
    if err!=nil {
        con.Close();
        running=false;
        return "Error in reading!";
    }
    fmt.Println();
    return string(buf);
}

// clientsender(): read from stdin and send it via network
func clientsender(cn net.Conn) {
    reader := bufio.NewReader(os.Stdin);
    for {
        fmt.Print("you> ");
        input, _ := reader.ReadBytes('\n');
        if string(input) == "/quit\n" {
            cn.Write([]byte("/quit"));
            running = false;
            break;
        }
        Log("clientsender(): send: ", string(input[0:len(input)-1]));
        cn.Write(input[0:len(input)-1]);
    }
}

// clientreceiver(): wait for input from network and print it out
func clientreceiver(cn net.Conn) {
    for running {
        fmt.Println(readabc(cn));
        fmt.Print("you> ");
    }
}

func main() {
    flag.Parse();
    running = true;
    Log("main(): start ");
    
    // connect
    destination := "127.0.0.1:9988";
    Log("main(): connecto to ", destination);
    cn, err := net.Dial("tcp", destination);
    test(err, "dialing");
    defer cn.Close();
    Log("main(): connected ");

    // get the user name
    fmt.Print("Please give you name: ");
    reader := bufio.NewReader(os.Stdin);
    name, _ := reader.ReadBytes('\n');

    //cn.Write(strings.Bytes("User: "));
    cn.Write(name[0:len(name)-1]);

    // start receiver and sender
    Log("main(): start receiver");
    go clientreceiver(cn);
    Log("main(): start sender");
    go clientsender(cn);
    
    // wait for quiting (/quit). run until running is true
    for ;running; {
        time.Sleep(1*1e9);
    }
    Log("main(): stoped");
}

gocode for golang 编程环境

作者:Ajian 发布时间:March 27, 2012 分类:Golang

前言:最近在学习go语言,我的编程环境是linux,使用vim,所以想整合下go的编程环境。在网上看到有一个gocode还不错可以自动补齐,相当的cool。

参考文章: http://www.mikespook.com/2011/03/gocode%E2%80%94%E2%80%94vim-%E5%92%8C-emacs-%E7%9A%84-golang-%E4%BB%A3%E7%A0%81%E8%87%AA%E5%8A%A8%E8%A1%A5%E5%85%A8/

gocode github地址: https://github.com/nsf/gocode

配置过程: 前提先要安装好go 配置好相关go的变量$GOROOT $GOBIN等
git clone git://github.com/nsf/gocode.git

cd gocode&&make install

我的是报错了make: *** No targets specified and no makefile found. Stop. 也不知道为什么 默认的clone出来没有makefile

只好从其它的分支里面弄出来一个

cd gocode&&git checkout go.r60&&go install

再配置vim

cd vim/&&./update.bash

确保 vim 启用了 filetype 插件,.vimrc 中应当有:filetype plugin on

基本上就没有问题了

附件带上我的vim配置文件和go vim环境自动安装脚本 可以 step by step 的协助集成 golang 相关脚本到 vim 中。(转自 http://www.mikespook.com/2011/09/%E4%B8%80%E4%B8%AA%E8%AE%BE%E7%BD%AE-golang-%E7%9A%84-vim-%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E7%9A%84%E8%84%9A%E6%9C%AC/)

下载地址:https://bitbucket.org/mikespook/learning_go_chinese/downloads/vim.sh

vimrc.txt vim配置文件(因为该blog上传指定了后缀才可以上传,所以下载保存为.vimrc就可以了)

效果图

羡慕的生活-保留勉励

作者:Ajian 发布时间:March 16, 2012 分类:生活记事

今天一个朋友发给我看的 忍不住保留下来 并且发布在自己的blog 祝福他们 也期待自己有这样的生活。

他们认识27年,恋爱11年,结婚8年,自助旅行10年,23个国家,十几万张照片,几十万文字。从大学生到小编辑再到自由摄影师,唯有梦想始终绽放微小的光芒】 这样的感情太让人感动了,爱情迟早褪去激情,唯有我们始终牵手旅行,找一个相爱的去浪迹天涯吧。。。。

like.jpg

openSUSE 12.1 nouveau 和 nvidia driver 互相转换

作者:Ajian 发布时间:March 15, 2012 分类:openSUSE

前言:自从openSUSE 集成了nouveau (是由第三方为NVIDIA显卡开发的一个开源3D驱动)主要是为了解决显卡驱动兼容问题,但是初期的nouveau 相当的不好用 很多图标之接都是crash的状态,所以我们一般采取将nouveau禁用,使用nvidia driver 也不是很麻烦,但后来我因为要支持双屏 不想去折腾了 所以又想从nvidia driver 撤回nouveau  因为他可以很方便的实现双屏的设置(一个竖屏一个横屏的效果)

Switch Nouveau to Nvidia driver

禁用Nouveau转换到Nvidia driver相关步骤(最少步骤):

  1. run "yast" (no quotes) and go to yast > System > /etc/sysconfig Editor > System > Kernel > NO_KMS_IN_INITRD and change it to "yes". 
  2. /etc/modprobe.d/50-blacklist.conf 末尾添加 blacklist nouveau
  3. 在Nvidia的官方网站找到相应的nvidia驱动 查看自己的显卡型号的方法
    lspci | grep VGA
    01:00.0 VGA compatible controller: nVidia Corporation GF116 [GeForce GTX 550 Ti] (rev a1)
  4. 下载完后 重启服务器进入level 3 , 即在grub的界面 下面输入3 即可
  5. 登陆之后 chmod +x NVIDIA-Linux-x86_64-270.41.06.run ; ./NVIDIA-Linux-x86_64-270.41.06.run 按提示安装即可
  6. 安装成功之后重启就可以进入系统了 试试3D效果还是比较酷的 会有一个nvidia的软件可以配置 系统自带的配置就不起作用了 相关配置文件 /etc/X11/xorg.conf

Switch Nvidia driver to Nouveau

恢复Nouveau配置:

  1. run "yast" (no quotes) and go to yast > System > /etc/sysconfig Editor > System > Kernel > NO_KMS_IN_INITRD and change it to "No".
  2.  /etc/modprobe.d/50-blacklist.conf  注释blacklist nouveau 
  3. 删除 rm -rf /etc/X11/xorg*
  4. 进入level 3 即在grub的界面 下面输入3 即可
  5. ./NVIDIA-Linux-x86_64-270.41.06.run -uninstall
  6. reinstall  kernel-desktop and  xorg-x11-driver-video-nouveau  我重新安装了这两个软件不过我没有再次测试是否是必要
  7. 重新启动 如果可以正常到登陆界面 基本上就没有问题了
  8. 登陆之后就可以做横屏和竖屏的配置了。发现的问题就是在横竖屏之间切换的时候会花掉 table切换下就又恢复了 还有视频好像没图像 还没查原因。
  9. 看下效果:

    效果图