2015年6月2日 星期二

GRUB 問題 出現 "Minimal BASH-like line editing...", grub>

step 1. boot live CD

step 2. find where is your hard disk for filesystem
   sudo fdisk -l
step 3. mount harddisk
   sudo mount /dev/sdxx /mnt   ( sdaxx depend on where is your hard disk)
   sudo mount --bind /dev /mnt/dev
   sudo mount --bind /sys /mnt/sys
   sudo mount --bind /proc /mnt/proc

step 4. change to target filesystem
   sudo chroot  /mnt

step 5. reinstall grub
   grub-install  /dev/sdx
   update-grub

step 6. leave chroot
   exit

step 7. umount 
   sudo umount /mnt/proc
   sudo umount /mnt/dev
   sudo umount /mnt/sys
   sudo umount /mnt

step 8. reboot system

2015年5月11日 星期一

ARM rootfs 語系設定

rootfs 太陽春, 解壓縮包時, 常常有一些語系相關的警告出現. 今天來看看如何設定.

打 locale 看到 LANGUAGE & LC_ALL 沒有定義, 另外有 3 個警告
debian@arm:~$ locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
debian@arm:~$

打 locale -a 可看到目前已經安裝語系.
debian@arm:~$ locale -a
C
C.UTF-8
POSIX

sudo nano /etc/default/locale
改 LANG=C.UTF-8
加 LANGUAGE=C.UTF-8
LC_ALL=C

若是要增加語系, 則用
locale-gen en_US.UTF-8
dpkg-reconfigure locales





ARM rootfs 減肥

檢查各目錄使用容量

du -hx --max-depth=1 /
du –sh /var/cache/apt/archives
du –sh /var/lib/apt/lists

清除記錄
apt-get clean
apt-get autoremove --purge

/usr/share/doc 及 /usr/share/man 的文件, 在 embedded 系統中沒有甚麼大用, 只是佔空間 40幾MB, 就看看如何把它們刪掉

建立 /etc/dpkg/dpkg.cfg.d/01_nodoc
加入如下內容, dpkg 在抓套件時, 就不會抓 doc
path-exclude /usr/share/doc/*
# we need to keep copyright files for legal reasons
path-include /usr/share/doc/*/copyright
path-exclude /usr/share/man/*
path-exclude /usr/share/groff/*
path-exclude /usr/share/info/*
# lintian stuff is small, but really unnecessary
path-exclude /usr/share/lintian/*
path-exclude /usr/share/linda/*
然後執行刪除既有 doc
find /usr/share/doc -depth -type f ! -name copyright|xargs rm || true
find /usr/share/doc -empty|xargs rmdir || true
rm -rf /usr/share/man/* /usr/share/groff/* /usr/share/info/*
rm -rf /usr/share/lintian/* /usr/share/linda/* /var/cache/man/*

在 /usr/share/locale 也有一堆用不到的語系資料, 可以用 localepurge 來移除

apt-get install localepurge


增加 /etc/locale.nopurge, 假設只留英語

####################################################
# This is the configuration file for localepurge(8).
####################################################

####################################################
# Uncommenting this string enables removal of localized
# man pages based on the configuration information for
# locale files defined below:

MANDELETE

####################################################
# Uncommenting this string causes localepurge to simply delete
# locales which have newly appeared on the system without
# bothering you about it:

DONTBOTHERNEWLOCALE

####################################################
# Uncommenting this string enables display of freed disk
# space if localepurge has purged any superfluous data:

SHOWFREEDSPACE

#####################################################
# Commenting out this string enables faster but less
# accurate calculation of freed disk space:

#QUICKNDIRTYCALC

#####################################################
# Commenting out this string disables verbose output:

#VERBOSE

#####################################################
# Following locales won't be deleted from this system
# after package installations done with apt-get(8):

en
en_US
en_US.ISO-8859-15
en_US.UTF-8


sudo localepurge
localepurge 會刪除不要的語系, 以後安裝新套件, localepurge 會被啟動, 將不要的刪除, 這樣會讓系統變慢. 最好是用完, 將 localpurge remove. 需要再重裝

如果不需要 X-windows, 相關套件也可以刪去

apt-get remove libx11-6 libx11-data

另外 /var 也有些肥胖, 如果不再安裝套件, 可以刪去內容物, 但是路徑要留下來
sudo find /var/cache/apt/ -type f -exec rm -v {} \;
sudo find /var/lib/apt/lists -type f -exec rm -v {} \;














ubuntu 使用 mini-httpd 當 web server

這個是不小心找到的, 原作者就是開發 thttpd , 當初的目的, 只是想知道用古老的 fork 有多慢, 作者實測認為有 apache 90% 的效能, 而 mini-httpd 有 GET, POST, HEAD method, 有密碼保護, 有CGI, 當作一個 embedded web server 跑一些簡易網頁應該是夠用了.

可到此一看究竟 http://acme.com/software/mini_httpd/

更奇怪的是 ubuntu 已經拋棄 thttpd, 但是 mini-httpd 還在它的套件庫裏面.


1. 下載 mini-httpd
sudo apt-get install mini-httpd
mini-httpd 被安裝到 /usr/sbin

同時會下載 apache2-utils, 會用到的應該就是 htpasswd, 其實在 mini-httpd source code 也有 htpasswd.c  若是由 source code rebuild, 應該不用下載 apache2-utils

2. 修改設定
sudo nano /etc/default/mini-httpd
找到 START=0, 改成 START=1

sudo nano /etc/mini-httpd.conf
找到 user, 將其改為 user=www-data
找到 data_dir, 將其改為 data_dir=/var/www

3. 啟動/暫停 mini-httpd
sudo /etc/init.d/mini-httpd start
sudo /etc/init.d/mini-httpd stop

4. log file 在 /var/log/mini-httpd.log

2015年5月10日 星期日

build CIVETWEB under Linux


mongoose 以前是 MIT 授權 (2013), 後來改成 GPL or 商業授權.
它標榜的是單一 source code, less memory footprint , 適合 embedded 使用.

現在有人拿 MIT 授權時代的 mongoose 來發展, 依然維持 MIT 授權
可在此找到 source code
https://github.com/bel2125/civetweb

因為需要 libssl.so & libcrypto.so
sudo apt-get install libssl-dev

http://sourceforge.net/projects/civetweb/files/1.6/
取得 civetweb.tar.gz 

make help
make build
make install
執行檔在 /usr/local/bin/civetweb
設定檔在  /usr/local/etc/civetweb.conf








ubuntu 14.04.2 安裝 thttpd

1. 安裝
用 sudo apt-get install thttpd  已經找不到 package

user@user-ubuntu140402:~$ sudo apt-get install thttpd
[sudo] password for user:
Reading package lists... Done
Building dependency tree    
Reading state information... Done
Package thttpd is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

E: Package 'thttpd' has no installation candidate

還好本家 debian 還是有這個 package

https://packages.debian.org/squeeze/thttpd
http://ftp.tw.debian.org/debian/pool/main/t/thttpd/

下載 deb, 用 software center 自動安裝

2. 修改設定
sudo cp /etc/defualt/thttpd /etc/defualt/thttpd.backup
sudo nano /etc/defualt/thttpd
find and change ENABLED=no to ENABLED=yes

3. 啟動/停止 thttpd
sudo /etc/init.d/thttpd start
sudo /etc/init.d/thttpd stop

4. 使用事項
a. 預設使用 /var/www 當網頁根目錄, 相關 html, 圖檔等資料存放位置
b. 設定檔 /etc/thttpd/thttpd.conf 可開啟或關掉 thttpd 某項功能






2015年3月31日 星期二

修改 ARM rootfs

用 cross system 在x86 OS 修改 ARM OS感到麻煩, 直接在 ARM target board 直接修改看看

用 su 權限
mkdir /mnt/rootfs
cd  /mnt/rootfs
tar zxvf   my_arm_rootfs.tgz
如果有 symbol link, tar 參數加 -h

for f in proc sys dev ; do mount --bind /$f /mnt/$f ; done

#!/bin/bash
mount --bind /dev  /mnt/rootfs/dev
mount --bind /proc/mnt/rootfs/proc
mount --bind /sys /mnt/rootfs/sys
mount --bind /dev/pts /mnt/rootfs/dev/pts
cp /etc/resolv.conf /mnt/rootfs/etc/resolv.conf
chroot /mnt/rootfs su

修改設定, 加減套件

最後做 rootfs 減肥

打 exit 離開 chroot

解除 ramfs
sync
umount /mnt/rootfs/dev
umount /mnt/rootfs/proc
umount /mnt/rootfs/sys
umount /mnt/rootfs/dev/pts

打包, 用 -C 設相對位置

tar zcvf my_new_rootfs.tgz -C /mnt/rootfs .

Linux console 自動登入

Linux 純文字模式登入需要 user name 及 password.

有些場合, 是機器之間對接, 不需要user name, password

編輯 /etc/login.defs
找到 NO_PASSWORD_CONSOLE, 這個設定是 login 時不用打password

修改例子 NO_PASSWORD_CONSOLE ttyS0:ttyS1

編輯 /etc/inittab
找到 getty, 有些OS是 agetty
原來像這樣
T0:123:respawn:/sbin/getty -L ttyS0 115200

修改例子 T0:123:respawn:/sbin/getty -n -l  /usr/sbin/autologin -L ttyS0 115200
-n 意思是不顯示 login 訊息
-l 意思是使用指定的 login 程式

但是 /usr/sbin 找不到 autologin

我們要自己準備 autologin.c,  code 如下, "your user name here" 換成你的 user name

#include "unistd.h"

int main() 
{
  execlp( "login", "login", "-f", "your user name here", 0);
}

產生執行檔
gcc autologin.c -o autologin

2015年3月27日 星期五

ARM Linux normal user can not access network, eg 無法 ping


下了 Ubuntu 的 ARM Linux rootfs, 在 root 時, ping 都正常, 但是一般user 就出現如下問題

ping www.google.com
ping: unknown host www.google.com

ping 8.8.8.8
socket: Permission denied

在 /etc/group   

inet:x:3003:root
net_raw:x:3004:root



然後給一般 user 使用 inet 權限

sudo gpasswd -a username inet

再使用 ping 出現


Ping: icmp open socket: Operation not permitted


原因是 ping 需要 suid, 那麼開權限給 user 

sudo chmod u+s `which ping`




2015年3月17日 星期二

Linux Daemon summary

Linux Daemon Writing HOWTO

http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
int main(void) {
        
        /* Our process ID and Session ID */
        pid_t pid, sid;
        
        /* Fork off the parent process */
        pid = fork();
        if (pid < 0) {
                exit(EXIT_FAILURE);
        }
        /* If we got a good PID, then
           we can exit the parent process. */
        if (pid > 0) {
                exit(EXIT_SUCCESS);
        }

        /* Change the file mode mask */
        umask(0);
                
        /* Open any logs here */        
                
        /* Create a new SID for the child process */
        sid = setsid();
        if (sid < 0) {
                /* Log the failure */
                exit(EXIT_FAILURE);
        }
        

        
        /* Change the current working directory */
        if ((chdir("/")) < 0) {
                /* Log the failure */
                exit(EXIT_FAILURE);
        }
        
        /* Close out the standard file descriptors */
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
        
        /* Daemon-specific initialization goes here */
        
        /* The Big Loop */
        while (1) {
           /* Do some task here ... */
           
           sleep(30); /* wait 30 seconds */
        }
   exit(EXIT_SUCCESS);
}
From here, you can use this skeleton to write your own daemons. Be sure to add in your own logging (or use the syslog facility), and code defensively, code defensively, code defensively!


#include 
#include 
#include 
#include 
#include 
#include 
int main(int argc, char* argv[])
{
FILE *fp= NULL;
pid_t process_id = 0;
pid_t sid = 0;
// Create child process
process_id = fork();
// Indication of fork() failure
if (process_id < 0)
{
printf("fork failed!\n");
// Return failure in exit status
exit(1);
}
// PARENT PROCESS. Need to kill it.
if (process_id > 0)
{
printf("process_id of child process %d \n", process_id);
// return success in exit status
exit(0);
}
//unmask the file mode
umask(0);
//set new session
sid = setsid();
if(sid < 0)
{
// Return failure
exit(1);
}
// Change the current working directory to root.
chdir("/");
// Close stdin. stdout and stderr
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// Open a log file in write mode.
fp = fopen ("Log.txt", "w+");
while (1)
{
//Dont block context switches, let the process sleep for some time
sleep(1);
fprintf(fp, "Logging info...\n");
fflush(fp);
// Implement and call some function that does core work for this daemon.
}
fclose(fp);
return (0);
}
$ gcc -Wall deamon.c -o deamon
$ sudo ./deamon
process_id of child process 2936
$ tail -f /Log.txt
Logging info...
Logging info...
Logging info...
Logging info...
Logging info...
Logging info...
Logging info...
Logging info...
Logging info...





創建 Daemon 程式

http://felix-lin.com/linux/%E5%89%B5%E5%BB%BA-daemon-%E7%A8%8B%E5%BC%8F/


#include <syslog.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#define MAXFD   64
void
daemon_init(const char *pname, int facility)
{
    int     i;
    pid_t   pid;
    if ( (pid = fork()) != 0)
        exit(0);            /* parent terminates */
    /* 1st child continues */
    setsid();               /* become session leader */
    signal(SIGHUP, SIG_IGN);
    if ( (pid = fork()) != 0)
        exit(0);            /* 1st child terminates */
    /* 2nd child continues */
    chdir("/");             /* change working directory */
    umask(0);               /* clear our file mode creation mask */
    for (i=0; i
        close(i);
    openlog(pname, LOG_PID, facility);
}
int main()
{
    int ii = 10;
    daemon_init("TEST", 0);
    while(ii) {
        syslog(LOG_INFO, "daemon example ... %d", ii--);
        sleep(10);
    }
    exit(0);
}



/*
 * daemonize.c
 * This example daemonizes a process, writes a few log messages,
 * sleeps 20 seconds and terminates afterwards.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>

static void skeleton_daemon()
{
    pid_t pid;

    /* Fork off the parent process */
    pid = fork();

    /* An error occurred */
    if (pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if (pid > 0)
        exit(EXIT_SUCCESS);

    /* On success: The child process becomes session leader */
    if (setsid() < 0)
        exit(EXIT_FAILURE);

    /* Catch, ignore and handle signals */
    //TODO: Implement a working signal handler */
    signal(SIGCHLD, SIG_IGN);
    signal(SIGHUP, SIG_IGN);

    /* Fork off for the second time*/
    pid = fork();

    /* An error occurred */
    if (pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if (pid > 0)
        exit(EXIT_SUCCESS);

    /* Set new file permissions */
    umask(0);

    /* Change the working directory to the root directory */
    /* or another appropriated directory */
    chdir("/");

    /* Close all open file descriptors */
    int x;
    for (x = sysconf(_SC_OPEN_MAX); x>0; x--)
    {
        close (x);
    }

    /* Open the log file */
    openlog ("firstdaemon", LOG_PID, LOG_DAEMON);
}

/* firstdaemon.c */
int main()
{
    skeleton_daemon();

    while (1)
    {
        //TODO: Insert daemon code here.
        syslog (LOG_NOTICE, "First daemon started.");
        sleep (20);
        break;
    }

    syslog (LOG_NOTICE, "First daemon terminated.");
    closelog();

    return EXIT_SUCCESS;
}
  • Compile the code: gcc -o firstdaemon daemonize.c
  • Start the daemon: ./firstdaemon
  • Check if everything is working properly: ps -xj | grep firstdaemon
  • The output should be similar to this one:
+------+------+------+------+-----+-------+------+------+------+-----+
| PPID | PID  | PGID | SID  | TTY | TPGID | STAT | UID  | TIME | CMD |
+------+------+------+------+-----+-------+------+------+------+-----+
|    1 | 3387 | 3386 | 3386 | ?   |    -1 | S    | 1000 | 0:00 | ./  |
+------+------+------+------+-----+-------+------+------+------+-----+
What you should see here is:
  • The daemon has no controlling terminal (TTY = ?)
  • The parent process ID (PPID) is 1 (The init process)
  • The PID != SID which means that our process is NOT the session leader (because of the second fork())
  • Because PID != SID our process can't take control of a TTY again
Reading the syslog:
  • Locate your syslog file. Mine is here: /var/log/syslog
  • Do a: grep firstdaemon /var/log/syslog
  • The output should be similar to this one:
  firstdaemon[3387]: First daemon started.
  firstdaemon[3387]: First daemon terminated.


daemon(3) - Linux man page

http://linux.die.net/man/3/daemon
#include <unistd.h>
int daemon(int nochdir, int noclose);
If nochdir is zero, daemon() changes the calling process's current working directory to the root directory  ("/"); otherwise, the current working directory is left unchanged.
If noclose is zero, daemon() redirects standard input, standard output and standard error to /dev/null; otherwise, no changes are made to these file descriptors.

example
Calling daemon() will detach your process from a controlling tty, close stdin/stdout, and will also fork & exit the parent so that your process becomes a child of init. For debugging, I added a -f option. If you specify -f, the program won't call daemon() so that you'll get your printfs. If you don't specify -f, the application will call daemon() and you won't see any more printfs.

#include 
#include 
#include 
#include 
#include 


int main(int argc, char** argv)
{
  bool run_in_foreground;
  int loop_count;
  int c;

  opterr = 0;

  while((c = getopt(argc, argv, "f")) != -1)
  {
    switch(c)
    {
    case 'f':
      run_in_foreground = true;
      break;

    case '?':
      printf("Unrecognized option '%c'.\n", optopt);
      return 1;

    default:
      abort();
    }
  }


  printf("This is my application...\n");

  if(!run_in_foreground)
  {
    printf("This is the last message you'll see, since I'm going to call daemon()\n");
    daemon(0,0);
  }
  else
  {
    printf("I'm in the foreground, so you'll still see my printfs\n");
  }


  for(loop_count = 0; loop_count < 10; loop_count++)
  {
    printf("Loop count is %d\n", loop_count);
    sleep(1);
  }

  return 0;
}

Upstart Intro, Cookbook and Best Practises
http://upstart.ubuntu.com/getting-started.html
http://upstart.ubuntu.com/cookbook/

How to correctly add a custom daemon to init.d?


Runit
http://smarden.org/runit/
http://smarden.org/runit/runsv.8.html

start-stop-daemon - start and stop system daemon programs

http://manpages.ubuntu.com/manpages/precise/man8/start-stop-daemon.8.html

systemd is a system and service manager for Linux
https://wiki.archlinux.org/index.php/systemd


Making scripts run at boot time with Debian

https://www.debian-administration.org/article/28/Making_scripts_run_at_boot_time_with_Debian

http://xmodulo.com/how-to-automatically-start-program-on-boot-in-debian.html

https://help.ubuntu.com/community/UbuntuBootupHowto

How to run a program when boot up?
http://en.kioskea.net/faq/3348-ubuntu-executing-a-script-at-startup-and-shutdown

To execute a script at startup of Ubuntu

  • Edit /etc/rc.local and add your commands
  • The script must always end with exit 0

To execute a script upon rebooting Ubuntu

  • Put your script in /etc/rc0.d
  • Make it executable (sudo chmod +x myscript)
  • Note: The scripts in this directory are executed in alphabetical order

The name of your script must begin with K99 to run at the right time. 

To execute a script at shutdown

  • Put your script in /etc/rc6.d
  • Make it executable (sudo chmod +x myscript)
  • Note: The scripts in this directory are executed in alphabetical order

The name of your script must begin with K99 to run at the right time




追蹤者