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




追蹤者