Blog

  • 无显示器-通过SD卡为cubieboard安装ubuntu linaro的ssh server

    最近买了一块cubieboard的板子,因为没有HDMI接口的现实器,板子买了一两个星期,还没用起来,买了跟HDMI转VGA的线也不能用。
    经过几番摸索,终于把系统安装好,并且用起来了。

    首先,通过下面的教程为SD卡安装ubuntu linaro系统:
    http://cn.cubieboard.org/forum.p … d=55&extra=page%3D1

    安装好了之后,启动,发现系统可以启动了,通过路由器,可以看到系统连接到网络,但是,要想在外部通过ssh连接到板子,出现拒绝连接的情况,没有安装ssh server。

    在论坛找到一个安装SSH SERVER 到SD的方法,但是不管用,还是连不上,ssh server没启动成功。
    http://cn.cubieboard.org/forum.p … d=56&extra=page%3D1

    下面自己编译代码的方案还没有试过:
    http://cn.cubieboard.org/forum.php?mod=viewthread&tid=54&extra=

    不过经过不断地努力和尝试,通过在linux宿主机编辑SD卡的信息,然后插入到板子上运行,记录一些日志信息,终于发现了些问题,也想到了解决办法。
    下面是发现的一些问题:
    查看/var/log/syslog经常出现sshd启动后,又退出的日志。
    在外面交叉编译的telnetd程序没启动成功,于是想到了在板子上编译的方法。

    下面说说我自己的方法:
    先下载telnetd的代码,在linux启动的时候,自动安装gcc编译器,然后编译程序,启动telnetd。通过外部程序telnet,再安装ssh。

    1.首先在宿主机下载telnetd的代码,拷贝到sd卡的opt目录下,并且在该目录下创建一个bin目录,修改权限。
    http://www.pudn.com/downloads166/ebook/detail757786.html
    下载的代码可能会编译不过,在宿主机试着编译一下,找出错误修改一下。
    记得有一个SHELLPATH的宏未定义,还有一些警告信息,修改一下即可。

    然后执行下面的命令:
    cp utelnetd.c /media/sdcard/opt
    cd /media/sdcard/opt
    sudo mkdir bin
    chmod 777 bin

    2.在Linux宿主机创建个人启动跟踪日志目录,然后编辑SD卡的Ubuntu linaro linux启动脚本。

    创建个人启动跟踪日志目录:
    cd /media/sdcard/var/log
    sudo mkdir sysstart
    chmod 777 sysstart

    编辑启动脚本.
    vi /media/sdcard/etc/init.d/rcS
    在脚本最后输入下面的内容:
    iptables -P INPUT ACCEPT
    iptables -P OUTPUT ACCEPT
    #通过runlevel >> /var/log/sysstart/runlevel.txt,查看到之前系统启动后的运行等级是2,改成标准模式3。
    init 3
    # 启动后自动安装下面的编译器
    apt-get –fix-missing -y install gcc
    apt-get –fix-missing -y install g++
    apt-get –fix-missing -y install build-essential
    #编译代码
    gcc -o /opt/bin/telnetd utelnetd.c
    #重定向方便出错时跟踪
    /opt/bin/telnetd -d >> /var/log/sysstart/telnetd.txt
    netstat -anp >> /var/log/sysstart/netstat-anp.txt
    ps aux >> /var/log/sysstart/ps-aux.txt

    保存后,把SC卡插入cubieboard,接上网线,上电启动,找出板子的IP,然后就可以telnet连接了。
    telnet 192.168.1.101

    >apt-get –fix-missing -y install openssh-server

    安装好了后,启动:
    /etc/init.d/ssh start

    然后就可以通过ssh连接板子的系统了。

    安装好了ssh后,再编辑/etc/init.d/rcS文件,去掉刚开始添加的那些内容。

    总结:
    后来发现,也可以在宿主机编辑SD卡的linux启动脚本,添加2行:
    apt-get –fix-missing -y install openssh-server
    /etc/init.d/ssh start
    启动的时候安装ssh server并启动,就省去了下载telnetd源码的工作了。

  • Linux用户切换导致github push出现Permission denied (publickey)错误

    最近尝试使用github托管代码,前面的流程还算比较顺利,没有遇到什么大问题,基本参考网上的流程就可以。

    首先,直接在网页上注册帐号,创建代码仓库repository,填写相关信息。

    然后,在linux客户端,用命令:git clone git@github.com:xxx/xxx.git 同步网页上创建repository到本地.

    在本地添加文件,git add, git commit等,具体的可以参考网上或者git –help。

    最后一步就是上传代码,git push, 如果没有生成本地公钥私钥对的,用ssh-keygen生成。

    然后把公钥的内容,通过网页,粘贴复制,提交到github中。

    在最后一步,要往github网站推送代码,出现问题了。

    出现以下的错误。

    试了几次,还是不行,就重新生成本地公钥密钥对,替换网站上的ssh key。

    用:ssh -T git@github.com 测试也还不行。

    从网上找的解决办法,大多都是官网帮助的翻译版。

    https://help.github.com/articles/generating-ssh-keys

    后来在网上找到这篇文章:

    http://www.cnblogs.com/nani/archive/2012/11/02/2751660.html

    发现有可能是本地密钥找不到的问题。

    用ssh -vT git@github.com测试,果然是

    原来是本地密钥对生成的路径不对,生成密钥用的是song用户,git push用的确实root用户。
    本地密钥对存储在/home/song/.ssh/ 目录下,用root用户推送,在root/.ssh/ 目录下找的密钥对,当然就不对了。
    切换到对应的用户,再次推送,就可以了。
    [song@centos6364 FixSizeMemPool]$ git push -u FixSizeMemPool master
    Enter passphrase for key ‘/home/song/.ssh/id_rsa’:
    Counting objects: 8, done.
    Delta compression using up to 2 threads.
    Compressing objects: 100% (7/7), done.
    Writing objects: 100% (7/7), 3.16 KiB, done.
    Total 7 (delta 0), reused 0 (delta 0)
    To git@github.com:vscz/FixSizeMemPool.git
       223eabd..8b275e2  master -> master
    Branch master set up to track remote branch master from FixSizeMemPool.
    被这个小问题给困扰了好几个小时,终于都解决了,看来调试非常重要啊,能快速找到问题的所在。
  • 创建单件模式的Logger类

    《C++高级编程》第二十六章的一个例子。
    /**
    * Logger.h
    *
    * Definition of a singleton logger class, implemented with static methods
    */
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <string>
    class Logger
    {
    public:
    static const std::string kLogLevelDebug;
    static const std::string kLogLevelInfo;
    static const std::string kLogLevelError;
    // Return a reference to the singleton logger object
    static Logger& instance();
    // Log a single message at the given log level
    void log(const std::string& inMessage, const std::string& inLogLevel);
    // Log a vector of messages at the given log level
    void log(const std::vector<std::string>& inMessage, const std::string& inLogLevel);
    protected:
    // static variable for the one-and-only instance
    static Logger sInstance;
    // Constant for the filename
    static const char* const kLogFileName;
    // Data member for the output stream
    std::ofstream mOutputStream;
    private:
    // 关键:私有的构造函数,不能实例化,因为实例化时类外部无法访问其内部的私有的构造函数
    Logger(void);
    ~Logger(void);
    };

    /**
    * Logger.cpp
    *
    * Implementation of a singleton logger class
    */
    #include “Logger.h”
    #include <string>
    using namespace std;
    const string Logger::kLogLevelDebug = “DEBUG”;
    const string Logger::kLogLevelInfo = “INFO”;
    const string Logger::kLogLevelError = “Error”;
    const char* const Logger::kLogFileName = “log.out”;
    // The static instance will be construct when the program starts and destructed when it ends.
    Logger Logger::sInstance;
    Logger::Logger(void)
    {
    mOutputStream.open(kLogFileName, ios_base::app);
    if (!(mOutputStream.good())) {
    cerr << “Unable to initialize the Logger!” << endl;
    }
    }
    Logger::~Logger(void)
    {
    mOutputStream.close();
    }
    Logger& Logger::instance()
    {
    return sInstance;
    }
    void Logger::log(const std::string& inMessage, const std::string& inLogLevel)
    {
    mOutputStream << inLogLevel << “:” << inMessage << endl;
    }
    void Logger::log(const std::vector<std::string>& inMessage, const std::string& inLogLevel)
    {
    for (size_t i=0; i<inMessage.size(); i++) {
    log(inMessage[i], inLogLevel);
    }
    }

    // TestTrueSingletonLogger.cpp
    #include “Logger.h”
    #include <vector>
    #include <string>
    int main(int argc, char **argv)
    {
    Logger::instance().log(“test message”, Logger::kLogLevelDebug);
    vector<string> items;
    items.push_back(“item1”);
    items.push_back(“item2”);
    Logger::instance().log(items, Logger::kLogLevelError);
    return 0;
    }

  • Linux wc 统计

    $ wc –help
    用法:wc [选项]… [文件]…
    Print newline, word, and byte counts for each FILE, and a total line if
    more than one FILE is specified. With no FILE, or when FILE is -,
    read standard input.
    -c, –bytes print the byte counts
    -m, –chars print the character counts
    -l, –lines print the newline counts
    -L, –max-line-length print the length of the longest line
    -w, –words print the word counts
    –help 显示此帮助信息并退出
    –version 输出版本信息并退出
    例如:
    统计tcp的连接数:netstat -an|grep tcp | wc -l

  • netstat+awk 查看tcp的网络连接状态

    执行以下命令:
    #netstat -n | awk ‘/^tcp/ {++state[$NF]} END {for(key in state) print key.”\t”.state[key]}’
    会得到类似下面的结果,具体数字会有所不同:
    FIN_WAIT_1 286
    FIN_WAIT_2 960
    SYN_SENT 3
    LAST_ACK 32
    CLOSING 1
    CLOSED 36
    SYN_RCVD 144
    TIME_WAIT 2520
    ESTABLISHED 352
    这条命令可以把当前系统的网络连接状态分类汇总。
    这条语句是在张宴那边看到,据说是从新浪互动社区事业部技术总监王老大那儿获得的,非常不错。
    返回参数的说明如下:
    SYN_RECV表示正在等待处理的请求数;
    ESTABLISHED表示正常数据传输状态;
    TIME_WAIT表示处理完毕,等待超时结束的请求数。
    ——————————————————————
    再来看看awk:
    /^tcp/
    滤出tcp开头的记录,屏蔽udp, socket等无关记录。
    state[]
    相当于定义了一个名叫state的数组
    NF
    表示记录的字段数,如上所示的记录,NF等于6
    $NF
    表示某个字段的值,如上所示的记录,$NF也就是$6,表示第6个字段的值,也就是TIME_WAIT
    state[$NF]
    表示数组元素的值,如上所示的记录,就是state[TIME_WAIT]状态的连接数
    ++state[$NF]
    表示把某个数加一,如上所示的记录,就是把state[TIME_WAIT]状态的连接数加一
    END
    表示在最后阶段要执行的命令
    for(key in state)
    遍历数组
    print key,”\t”,state[key]
    打印数组的键和值,中间用\t制表符分割,美化一下。

  • Freetds 连接SQL Server 错误:Unexpected EOF from the server

    安装

    安装好freetds 0.82后,用tsql连接数据库,会出现以下错误:

    locale is "en_US.UTF-8"
    locale charset is "UTF-8"
    using default charset "UTF-8"
    Error 20017 (severity 9):
            Unexpected EOF from the server
            OS error 115, "Operation now in progress"
    Error 20002 (severity 9):
            Adaptive Server connection failed

    There was a problem connecting to the server

    程序连接也一样,Unexpected EOF from the server。

    查看网上的内容,可能与配置有关,于是修改配置文件freetds.conf,将对应的内容修改为以下的值:

    tds version = 8.0

    再次连接,成功连接到SQL Server。

  • gcc编译文件名后缀不匹配错误

    用gcc编译一个xx.cpp的文件或出现如下错误:
    /tmp/ccq5K20D.o:(.eh_frame+0x12): undefined reference to `__gxx_personality_v0′
    用g++可以编译,如果要用gcc编译,改边文件后缀为*.c

  • ACE WSA Startup not initialized 问题

    将属性->配置属性->常规(Gerneral)
    字符集(Character Set): Use Unicode Character Set
    改为
    Character Set:未设置( Not Set)
    这样就ok了
    默认ACE使用多字节字符集
    如果你想ACE使用 Unicode 字符集,
    需要添加下面两行
    #define ACE_HAS_WCHAR
    #define ACE_USE_WCHAR

  • Ubuntu mysql 不能远程连接的问题

    Ubuntu10.04上自带的MySQL,执行了
    apt-get install mysql
    安装完mysql-server
    启动mysql
    start
    本地可以连接进入数据库。
    -uroot -p
    设置了远程访问权限:
    mysql> grant all PRIVILEGES on *.* to admin@’%’ identified by ‘123456’;
    Query OK, 0 rows affected (0.04 sec)
    mysql> use information_schema
    mysql> select * from user_privileges;
    查询到有下面的结果:’admin’@’%’,说明mysql已经授权远程连接。
    在windows下访问Ubuntu的数据库,连接不上,但是Ubuntu上安装的apache可以访问。
    用iptalbes添加端口3306后也无法访问。
    :~# iptables -A INPUT -p tcp –dport 3306 -j ACCEPT
    Ubuntu上查看Mysql网络连接:
    :~# netstat -an |grep 3306
    tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN
    本地端口也在监听
    :~# ufw status
    Firewall not loaded
    本地防火墙未打开
    后来在网上找到一个解决办法:
    打开 /etc/mysql/my.cnf 文件,找到 bind-address = 127.0.0.1 修改为 bind-address = 0.0.0.0
    重启mysql : sudo /etc/init.d/mysql restart
    就好了,我在windows下就可以连上了。

  • Apache自带的WWW性能测试工具ab

    ab(ApacheBench)是Apache自带的超文本传输协议(http)性能测试工具。安装好Apache后可以在其bin目录找到它。使用非常方便,例如我们要“对index.php页进行50个并发,总共1000次请求的测试”,只需要用命令:ab -n 1000 -c 50 http://127.0.0.1/index.php
    就会有测试的结果。