2017年4月16日日曜日

分割数指定でファイル分割

ファイルを決まった個数に分割したいことはあるが、分割数を指定して分けるコマンドが見当たらず困ることがある。



例えば25行のファイルを8分割したい場合など、split で3行分割指定では3×8+1 の9分割となり、4行分割指定では4×6+1の7分割となり微妙に困る。そんな時、自前で分割数指定でわけるコマンドを持っていると楽できるかもしれない。



1.shellで分割

#! /bin/sh

if [ "$#" != 3 ]
then
    echo "Usage : split2.sh divisor input base"
    exit 1
fi

divisor=$1
input=$2
base=$3

c_start=0
c_end=0
quotient=0
toomach=0
total=0
part=0

total=`wc -l < $input`
quotient=`expr $total / $divisor`
toomuch=`expr $total % $divisor`

divisor=`expr $divisor - 1`
#printf "%d %d %d\n" $total $qutient $toomuch

for no in `seq 0 $divisor`
do
    if [ $no -lt $toomuch ]
    then
        c_start=`expr $c_end + 1`
        c_end=`expr $c_start + $quotient`
    else
        c_start=`expr $c_end + 1`
        c_end=`expr $c_start + $quotient - 1`
    fi
    file=`printf "%s%02d" $base $no`
    cmd=`echo "$cmd -e '$c_start,$c_end w $file'"`

    cnt=`expr $c_end - $c_start + 1`
    printf "Part[%d] Start[%08d] End[%08d] Cnt[%08d]\n" `expr $no + 1` $c_start $c_end $cnt
done

sh -c "sed -n $cmd $input"

2.perlで分割

#! /usr/bin/perl

if (scalar(@ARGV) != 3) {
  printf(STDERR "Usage : split2.pl divisor input base\n");
  exit(1);
}

$divisor  = shift(@ARGV);
$input    = shift(@ARGV);
$base     = shift(@ARGV);

$c_start  = 0;
$c_end    = 0;
$quotient = 0;
$toomach  = 0; 
$total    = 0; 
$part     = 0; 

if (!open(FD,$input)) {
  printf(STDERR "Can't open file[%s]\n",$input);
  exit(1);
}
while(<FD>) {$total++}
close(FD);

$quotient = int($total / $divisor);
$toomuch  = int($total % $divisor);

foreach $no (0..($divisor-1)) {
  my($file) = sprintf("%s%02d",$base,$no);
  if (!open(${$file},">$file")) {
    printf(STDERR "Can't open file[%s]\n",$file);
    exit(1);
  }
}

if (!open(FD,$input)) {
  printf(STDERR "Can't open file[%s]\n",$input);
  exit(1);
}
my($cnt) = 0;
while(<FD>) {
  $cnt++;
  if ($cnt > $c_end) {
    if($part < $toomuch)  {
      $c_start = $c_end + 1;
      $c_end   = $c_start + $quotient;
    }
    else {
      $c_start = $c_end + 1;
      $c_end   = $c_start + $quotient - 1;
    }
    printf("Part[%d] Start[%08d] End[%08d] Cnt[%08d]\n",
           $part + 1,$c_start,$c_end,$c_end - $c_start + 1); 
    $part++;
  }
  my($file) = sprintf("%s%02d",$base,$part-1);
  printf({${$file}} "%s",$_);
}

close(FD);

foreach $no (0..($divisor-1)) {
  my($file) = sprintf("%s%02d",$base,$no);
  close(${$file});
}


3.rubyで分割

#! /usr/bin/ruby

if (ARGV.length != 3)
  printf("Usage : split2.rb divisor input base\n")
  exit(1)
end

divisor  = ARGV[0].to_i
input    = ARGV[1]
base     = ARGV[2]

c_start  = 0
c_end    = 0
quotient = 0
toomuch  = 0
total    = 0
part     = 0
fplist   = []

f = File.open(input,"r");
f.each_line do |line|
  total += 1
end
f.close()

divisor.times do |no|
  fplist[no] = open("%s%02d"%[base,no],"w")  
end

quotient = (total / divisor).to_i
toomuch  = (total % divisor).to_i

cnt = 0
f = File.open(input,"r");
f.each_line do |line|
  cnt += 1
  if (cnt > c_end)
    if (part < toomuch) 
      c_start = c_end + 1
      c_end   = c_start + quotient
    else
      c_start = c_end + 1
      c_end   = c_start + quotient - 1
    end
    printf("Part[%d] Start[%08d] End[%08d] Cnt[%08d]\n",
           part + 1,c_start,c_end,c_end - c_start + 1)
    part += 1
  end
  fplist[part-1].printf("%s",line)
end
f.close()

divisor.times do |no|
  fplist[no].close
end

4.pythonで分割

#! /usr/bin/python

import sys

if len(sys.argv) != 4:
  print "Usage : split2.py divisor input base"
  sys.exit(1)

divisor  = int(sys.argv[1])
input    = sys.argv[2]
base     = sys.argv[3]

c_start  = 0
c_end    = 0
quotient = 0
toomuch  = 0
total    = 0
part     = 0
fplist   = []

f = open(input,"r")
for line in f:
  total += 1
f.close()

quotient = total / divisor
toomuch  = total % divisor

for no in range(0, divisor):
  f = open("%s%02d"%(base,no),"w")
  fplist.append(f)

cnt = 0
f = open(input,"r")
for line in f:
  cnt += 1
  if cnt > c_end:
    if part < toomuch:
      c_start = c_end + 1
      c_end   = c_start + quotient
    else:
      c_start = c_end + 1
      c_end   = c_start + quotient - 1
    print "Part[%d] Start[%08d] End[%08d] Cnt[%08d]" \
          %(part+1,c_start,c_end,c_end - c_start + 1)
    part += 1
  fplist[part-1].write("%s"%line)
f.close()

for out in fplist:
  out.close()

5.lispで分割

#! /usr/bin/clisp

(if (not (equal (length *args*) 3))
    (progn
      (format t "Usage split.lisp divisor input base")
      (exit 1)))

(setq divisor (parse-integer (car *args*)))
(setq input   (car (cdr *args*)))
(setq base    (caddr *args*))

(setq c_start  0)
(setq c_end    0)
(setq total    0)
(setq quotient 0)
(setq toomuch  0)
(setq part     0)
(setq fplist  '())

(let ((in (open input :direction :input)))
  (loop for line = (read-line in nil)
 while line do (setq total (+ total 1)))
  (close in))

(setq quotient (floor (/ total divisor)))
(setq toomuch  (floor (mod total divisor)))

;;
(dotimes (no divisor)
  (let ((out (open (format nil "~A~2,'0D" base no) :direction :output)))
    (push out fplist)))
;;    (format t "~A~2,'0D~%" base no)))
(nreverse fplist)

(let
    ((in (open input :direction :input))
     (cnt 0)
     (line ""))
  (loop
   (setq line (read-line in nil))
   (if (null line)
       (quit))
   (setq cnt (+ cnt 1))
   (if (> cnt c_end)
       (progn
  (if (< part toomuch)
      (progn
        (setq c_start (+ c_end 1))
        (setq c_end   (+ c_start quotient)))
    (progn
      (setq c_start (+ c_end 1))
      (setq c_end   (+ c_start quotient -1))))
  (setq part (+ part 1))
  (format t "Part[~D] Start[~8,'0D] End[~8,'0D] Cnt[~8,'0D]~%"
   part c_start c_end (+ (- c_end c_start) 1))))
   (format (elt fplist (- part 1)) "~A~%" line))
   (close in))
;;
(dotimes (no divisor)
  (close (pop fplist)))

6.javaで分割

import java.io.*;
import java.util.*;

class split2 {
  void split(int divisor, String input, String base) throws Exception {
    BufferedReader br = null;
    List<PrintWriter>fplist = null;
    String line = "";
    int total = 0;
    int c_start = 0;
    int c_end = 0;
    int part = 0;
    int quotient = 0;
    int toomuch = 0;
    int cnt =0;

    br = new BufferedReader(new FileReader(input));
    while((line=br.readLine())!=null) {
      total++;
    }
    br.close();

    fplist = new ArrayList<PrintWriter>();
    for(int no=0;no<divisor;no++) {
      String file = String.format("%s%02d",base,no);
      PrintWriter pw = new PrintWriter(
                           new BufferedWriter(new FileWriter(file)));
      fplist.add(pw);
    }

    quotient = total / divisor;
    toomuch  = total % divisor;

    cnt = 0;
    br = new BufferedReader(new FileReader(input));
    while((line=br.readLine())!=null) {
      cnt++;
      if (cnt > c_end) {
        if (part < toomuch) {
          c_start = c_end + 1;
          c_end   = c_start + quotient;
        } 
        else {
          c_start = c_end + 1;
          c_end   = c_start + quotient - 1;
        }
        System.out.printf("Part[%d] Start[%08d] End[%08d] Cnt[%08d]\n",
                          part+1,c_start,c_end,c_end-c_start+1);
        part++;
      }
      fplist.get(part-1).printf("%s\n",line);
    }
    br.close();

    for(int no=0;no<divisor;no++) {
      fplist.get(no).close();
    }
  } 
  
  public static void main(String args[]) throws Exception {
    if (args.length != 3) {
      System.out.printf("Usage : split2 divisor input base\n");
      System.exit(1);
    }

    int    divisor = Integer.parseInt(args[0]);
    String input   = args[1];
    String base    = args[2];

    split2 obj = new split2();
    obj.split(divisor,input,base);
  }
}

7.C言語で分割

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int
split(int divisor, char *input, char *base)
{
    FILE **fplist   = NULL;
    FILE  *fp       = NULL;
    int    c_start  = 0;
    int    c_end    = 0;
    int    quotient = 0;
    int    toomuch  = 0;
    int    total    = 0;
    int    part     = 0;
    int    cnt      = 0;
    int    no       = 0;
    char   buf[2048];

    fplist = calloc(sizeof(FILE *),divisor);
    if (!fplist) {
        fprintf(stderr,"calloc error!\n");
        return(1);
    }

    fp = fopen(input,"r");
    if (!fp) {
        fprintf(stderr,"Can't open file[%s]\n",input);
        return(1);
    }
    while(fgets(buf, sizeof(buf), fp)) {
        total++;
    }
    if (fclose(fp)) {
        fprintf(stderr,"Can't open file[%s]\n",input);
        return(1);
    }

    quotient = total / divisor;
    toomuch  = total % divisor;

    for(no=0;no<divisor;no++) {
        char file[128];
        sprintf(file,"%s%02d",base,no);
        fp = fopen(file,"w");
        if (!fp) {
            fprintf(stderr,"Can't open file[%s]\n",file);
            return(1);
        }
        fplist[no] = fp;
    }

    fp = fopen(input,"r");
    if (!fp) {
        fprintf(stderr,"Can't open file[%s]\n",input);
        return(1);
    }
    cnt = 0;
    while(fgets(buf, sizeof(buf), fp)) {
        cnt++;
        if (cnt > c_end) {
            if (part < toomuch) {
                c_start = c_end + 1;
                c_end   = c_start + quotient;
            }
            else {
                c_start = c_end + 1;
                c_end   = c_start + quotient - 1;
            }
            printf("Part[%d] Start[%08d] End[%08d] Cnt[%08d]\n",
                   part+1, c_start, c_end, c_end-c_start+1);
            part++;
        }
        if (!fprintf(fplist[part-1],"%s",buf)) {
            fprintf(stderr,"part [%d] write error\n",part);
            return(1);
        }
    }
    if (fclose(fp)) {
        fprintf(stderr,"Can't open file[%s]\n",input);
        return(1);
    }
    
    for(no=0;no<divisor;no++) {
        char file[128];
        sprintf(file,"%s%02d",base,no);
        if (fclose(fplist[no])) {
            fprintf(stderr,"Can't open file[%s]\n",file);
            return(1);
        }
    }
    
    return(0);
} 

int
main(int argc, char *argv[]) 
{
    int   divisor = 0;
    char *p       = NULL;
    char  input[128];
    char  base[128];

    if (argc != 4) {
        fprintf(stderr,"Usage : split2 divisor input base\n");
        exit(1);
    }
 
    for(p=argv[1];(*p)!='\0';p++) {
        if (!isdigit(*p)) {
            fprintf(stderr,"not a number! [%s]\n",argv[1]);
            exit(1);
        }
    }

    divisor = atoi(argv[1]);
    strcpy(input, argv[2]);
    strcpy(base, argv[3]);

    split(divisor, input, base);
}

8.速度比較

=== sh ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m2.696s
user    0m0.460s
sys     0m2.140s

=== perl ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m2.122s
user    0m1.736s
sys     0m0.216s

=== ruby ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m2.510s
user    0m2.048s
sys     0m0.256s

=== python ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m1.199s
user    0m0.832s
sys     0m0.228s

=== lisp ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m24.201s
user    0m21.632s
sys     0m2.012s

=== java ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m2.631s
user    0m2.936s
sys     0m0.468s

=== c ===
Part[1] Start[00000001] End[00125000] Cnt[00125000]
Part[2] Start[00125001] End[00250000] Cnt[00125000]
Part[3] Start[00250001] End[00375000] Cnt[00125000]
Part[4] Start[00375001] End[00500000] Cnt[00125000]
Part[5] Start[00500001] End[00625000] Cnt[00125000]
Part[6] Start[00625001] End[00750000] Cnt[00125000]
Part[7] Start[00750001] End[00875000] Cnt[00125000]
Part[8] Start[00875001] End[01000000] Cnt[00125000]

real    0m0.484s
user    0m0.236s
sys     0m0.224s

2017年4月15日土曜日

tree コマンドの作成

ubuntu などでは最初からインストールされないコマンドで使いたくなるのが tree コマンドである。 たが、開発環境の制約から自由にプログラムを追加できない場合も多い。



そんな場合に利用可能な言語で自前のツールとして用意しておくと助かる場合もある。以下は、シンボリックリンクや日本語のソート(sjisコード順)には対応せず、単純なソートと再帰呼び出しの組み合わせである。

  • perl で tree コマンド作成
  • ruby で tree コマンド作成
  • python で tree コマンド作成
  • clisp で tree コマンド作成
  • java で tree コマンド作成
  • C言語 で tree コマンド作成
  • 速度比較

    1.perl で tree コマンド作成


    #! /usr/bin/perl
    use utf8;
    #use Encode qw/encode decode/;
    use Encode;
    
    if (scalar(@ARGV) == 0) {
      $root_dir = "."
    }
    else {
      $root_dir = shift(@ARGV);
    }
    printf("%s\n",$root_dir);
    &tree("",$root_dir);
    
    sub tree {
      my($depth,$dir) = @_;
    
      if (!opendir(FD,$dir)) {
        printf("Can't open dir[%s]\n",$dir);
        exit(1);
      }
    
      my(@list) = ();
      foreach $file (readdir(FD)) {
        if ($file =~ /^[.]$/ || $file =~ /^[.][.]$/) {
          next;
        }
    #    $file = decode('UTF-8', $file);
    #    $file = encode('Shift_JIS', $file);
        push(@list,$file)
      }
      close(fd);
    
      my($cnt) = 0;
      foreach $file (sort @list) {
        $cnt++;
    
    #    $file = decode('Shift_JIS', $file);
    #    $file = encode('UTF-8', $file);
        my($fullpath) = $dir . "/" . $file;
        if ( -d $fullpath ) {
          if (scalar(@list) == $cnt) {
            printf("%s`-- %s\n",$depth,$file);
            tree($depth . "    ",$fullpath);
          }
          else {
            printf("%s|-- %s\n",$depth,$file);
            tree($depth . "|   ",$fullpath);
          }
        }
        else {
          if (scalar(@list) == $cnt) {
            printf("%s`-- %s\n",$depth,$file);
          }
          else {
            printf("%s|-- %s\n",$depth,$file);
          }
        }
      }
    }
    

    2.ruby で tree コマンド作成


    #! /usr/bin/ruby
    
    def tree(depth,dir)
      f =  Dir.open(dir);
      list = []
      f.each{ |file|
        if (file =~ /^[.]$/ || file =~ /^[.][.]$/)
          next
        end
    #    file = file.encode("Shift_JIS", :undef => :replace, :replace => "*")
        list.push(file)
      }
    
      cnt = 0
      list.sort.each {|file|
    #    file = file.encode("UTF-8")
        cnt = cnt +1
    
        fullpath = dir + "/" + file
    
        if (File.ftype(fullpath) == "directory")
          if (list.length == cnt)
            printf("%s`-- %s\n",depth,file)
            tree(depth + "    ",fullpath)
          else
            printf("%s|-- %s\n",depth,file)
            tree(depth + "|   ",fullpath)
          end
        else
          if (list.length == cnt)
            printf("%s`-- %s\n",depth,file)
          else
            printf("%s|-- %s\n",depth,file)
          end
        end
     }
    end
    
    if (ARGV.size() == 0)
      root_dir = "."
    else
      root_dir = ARGV[0]
    end
    printf("%s\n",root_dir)
    tree("",root_dir)
    

    3.python で tree コマンド作成


    #! /usr/bin/python
    
    import os
    import sys
    
    def tree(depth,dir):
      files = sorted(os.listdir(dir))
      cnt = 0
    
      for file in files:
        fullpath =  dir + "/" + file
        cnt = cnt + 1
    
        if os.path.isdir(fullpath):
          if len(files) == cnt:
            print "%s`-- %s"%(depth,file)
            tree(depth + "    " ,fullpath)
          else:
            print "%s|-- %s"%(depth,file)
            tree(depth + "|   " ,fullpath)
        else:
          if len(files) == cnt:
            print "%s`-- %s"%(depth,file)
          else:
            print "%s|-- %s"%(depth,file)
    
    root_dir = "."
    if len(sys.argv) > 1:
      root_dir = sys.argv[1]
    
    print root_dir
    tree("",root_dir)
    

    4.clisp で tree コマンド作成


    #! /usr/bin/clisp
    
    (defun fname-chop(tfile)
      ;;
      (let ((buf (namestring tfile)))
           (setq ch (subseq buf (- (length buf) 1) (length buf)))
           (if (equal ch "/")
               (subseq buf 0 (- (length buf) 1))
               (subseq buf 0 (length buf)))))
    
    (defun tree(depth dir)
      
      (let (
        (list (concatenate 
               'list
               (directory (concatenate 'String dir "*/"))
               (directory (concatenate 'String dir "*"))))
        (tmp "")
        (cnt 0))
    
        (sort list #'string< :key #'fname-chop)
    
        (dolist (file list)
          (progn 
            (incf cnt)
            (setq tfile (namestring file))
            (setq tfile (subseq tfile 0 (- (length tfile) 1)))
    
            (if (equal (file-namestring file) "")
              (if (equal (length list) cnt)
                (progn 
                  (format t "~A`-- ~A~%" depth (file-namestring tfile))
                  (tree (concatenate 'String depth "    ") (namestring file))
                  )
                (progn 
                  (format t "~A|-- ~A~%" depth (file-namestring tfile))
                  (tree (concatenate 'String depth "|   ") (namestring file))
                  ))
              (if (equal (length list) cnt)
                (progn 
                  (format t "~A`-- ~A~%" depth (file-namestring file))
                  )
                (progn 
                  (format t "~A|-- ~A~%" depth (file-namestring file))
                  )))))))
    
    (let 
      ((root_dir ""))
      (if (equal (length *args*) 0)
        (setq root_dir "./")
        (setq root_dir (car *args*)))
      (if (not (equal (subseq root_dir (- (length root_dir) 1) (length root_dir)) "/")) 
        (format t "test01 [dir]"))
      (format t "~A~%" root_dir)
      (tree "" root_dir))
    

    5.java で tree コマンド作成


    import java.io.*;
    import java.util.*;
    
    class tree {
      void tree(String depth,File dir) {
        File[] files = dir.listFiles();
        int cnt = 0; 
    
        Arrays.sort(files);
    
        if (files == null) {
          return;
        }
        for(File file: files) {
          cnt++;
          if (file.isDirectory()) {
            if (files.length == cnt) {
              System.out.printf("%s`-- %s\n",depth,file.getName());
              tree(depth + "    ",new File(file.getAbsolutePath())); 
            }
            else {
              System.out.printf("%s|-- %s\n",depth,file.getName());
              tree(depth + "|   ",new File(file.getAbsolutePath())); 
            }
          }
          else {
            if (files.length == cnt) {
              System.out.printf("%s`-- %s\n",depth,file.getName());
            }
            else {
              System.out.printf("%s|-- %s\n",depth,file.getName());
            }
          }
        }
      }
    
      public static void main(String args[]) {
        String root_dir = ".";
    
        if (args.length != 0) {
          root_dir = args[0];
        }
        System.out.printf("%s\n",root_dir);
    
        tree obj = new tree();
        obj.tree("",new File(root_dir));
      }
    }
    

    6.C言語 で tree コマンド作成


    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <dirent.h>
    #include <string.h>
    #include <unistd.h>
    
    typedef struct dirent DENT;
    typedef struct {
      int   cnt;
      DENT *list;
    } DENT_B;
    
    int
    comp(src,dst) 
    DENT *src;
    DENT *dst;
    {
        return(strcmp(src->d_name,dst->d_name));
    }
    
    int
    list_alloc(base)
    DENT_B *base;
    {
        if (!base->list) {
            base->list = malloc(sizeof(DENT)*base->cnt);
            if (!base->list) {
                return(1);
            }
        }
        else {
            base->list = realloc(base->list, sizeof(DENT)*base->cnt);
        } 
    
        return(0);
    }
    
    int
    mklist(base,dir) 
    DENT_B *base;
    char   *dir;
    {
        DIR  *dp   = NULL;
        int   cnt  = 0;
        DENT *dent = NULL;
    
        dp=opendir(dir);
        if (!dp) {
            fprintf(stderr,"Can't open directory(%s)\n",dir);
            return(1);
        }
    
        base->cnt = 0;
        while(dent = readdir(dp)) {
            if (dent == (struct dirent *)-1) {
                fprintf(stderr,"Can't read directory(%s)\n",dir);
                return(1);
            }
    
            if (!strcmp(dent->d_name,".") ||
                !strcmp(dent->d_name,"..")) {
                continue;
            }
            
            base->cnt++;
            if (list_alloc(base)) {
                fprintf(stderr,"Can't alloc memory\n");
                return(1);
            }
    
            memcpy(&base->list[base->cnt-1],dent,sizeof(DENT));
        }
    
        if (closedir(dp)) {
            fprintf(stderr,"Can't close directory(%s)\n",dir);
            return(1);
        }
    
        return(0);
    }
    
    int
    tree(depth, dir)
    char *depth;
    char *dir;
    {
        DENT_B  base;
        int     cnt;
        char    fullpath[512];
        char    depth_tmp[512];
        struct stat dstat;
    
        memset(&base,0x00,sizeof(base));
    
        if (mklist(&base,dir)) {
            fprintf(stderr,"mklist error(%s)\n",dir);
            return(1);
        }
    
        qsort(base.list,base.cnt,sizeof(DENT),comp);
    
        for(cnt=0;cnt<base.cnt;cnt++) {
            sprintf(fullpath,"%s/%s",dir,base.list[cnt].d_name);
            if (stat(fullpath,&dstat)) {
                fprintf(stderr,"stat error(%s)\n",fullpath);
                return(1);
            }
            if (dstat.st_mode & S_IFDIR) {
                if (cnt+1 == base.cnt) {
                    printf("%s`-- %s\n",depth,base.list[cnt].d_name);
                    sprintf(depth_tmp,"%s    ",depth);
                    tree(depth_tmp,fullpath);
                }
                else {
                    printf("%s|-- %s\n",depth,base.list[cnt].d_name);
                    sprintf(depth_tmp,"%s|   ",depth);
                    tree(depth_tmp,fullpath);
                }
            }
            else {
                if (cnt+1 == base.cnt) {
                    printf("%s`-- %s\n",depth,base.list[cnt].d_name);
                }
                else {
                    printf("%s|-- %s\n",depth,base.list[cnt].d_name);
                }
            }
        }
    
        free(base.list);
    
        return(0);
    }
    
    int
    main(argc,argv)
    int argc;
    char *argv[];
    {
        char *root_dir = NULL;
    
        root_dir = ".";
        if (argc > 1) {
            root_dir = argv[1];
        }
        printf("%s\n",root_dir);
        if (tree("",root_dir)!=0) {
           exit(1);
        }
        exit(0);
    }
    

    7.速度比較(2455 directories, 22931 files)


    == perl ==
    
    real    0m0.202s
    user    0m0.112s
    sys     0m0.088s
    
    == ruby ==
    
    real    0m0.333s
    user    0m0.196s
    sys     0m0.112s
    
    == python ==
    
    real    0m0.234s
    user    0m0.116s
    sys     0m0.112s
    
    == lisp ==
    
    real    0m2.564s
    user    0m1.736s
    sys     0m0.792s
    
    == java ==
    
    real    0m1.050s
    user    0m1.472s
    sys     0m0.432s
    
    == C ==
    
    real    0m0.101s
    user    0m0.020s
    sys     0m0.080s
    
    

  • 2017年4月9日日曜日

    ubuntu に oracle client をインストール

    ubuntu にオラクルクライアントをインストールし、リモートのオラクルデータベースに接続する。




    1.事前準備として以下の構成のディレクトリを作成
     /mnt/vbox/share/oracle12c 
     |-- database : linuxx64_12201_client.zip を展開
     `-- inst12c : 以下、スクリプト client.sh を作成
    

    ※ client.sh
    #! /bin/sh
    
    # 
    PKG="$PKG libaio1"
    PKG="$PKG libaio-dev"
    PKG="$PKG default-jre"
    #
    #
    apt-get install $PKG
    #
    ##
    ln -s  /usr/bin/awk /bin/awk
    #
    ##
    groupadd -g 54321 oinstall
    
    useradd -u 1200          \
            -g oinstall      \
            -d /home/oracle  \
            -m oracle
    
    #
    mkdir -p /u01/app/oracle
    chown -R oracle:oinstall /u01/app
    chmod -R 775 /u01
    


    2.client.sh を実行後、オラクルクライアントのインストールを行う。
    # cd /mnt/vbox/share/oracle12c/inst12c
    $ sudo -s 
    # ./client.sh
    # su - oracle
    # cd /mnt/vobx/share/oracle12c/client
    # ./runInstaller -jreloc /usr/lib/jvm/default-java
    

    3..profile に以下の環境変数を設定
    export ORACLE_BASE=/u01/app/oracle
    export ORACLE_HOME=$ORACLE_BASE/product/12.2.0/client_1
    export ORACLE_SID=orcl
    export PATH=$ORACLE_HOME:$PATH
    export NLS_LANG=JAPANESE_JAPAN.UTF8
    export LD_LIBRARY_PATH=$ORACLE_HOME
    

    4.接続確認
     1) コンテナ形式のデータベースに接続
    $ source ~/.profile
    $ sqlplus system/passwd@IPaddress:1521/orcl.oracle.com  (CDBに接続)
    $ sqlplus scott/tiger@IPaddress:1521/orclpdb.oracle.com (PDBに接続)
    

     2) 従来型のデータベースに接続
    $ source ~/.profile
    $ sqlplus scott/tiger@IPaddress:1521/orcl.oracle.com
    

    5.tnsnames.ora を定義してサービス名で接続
     $ORACLE_HOME/network/admin/tnsname.ora にサービス名を定義し、その名称で接続
    $ cat $ORACLE_HOME/network/admin/tnsnames.ora
    SRV_PDB = 
     ( DESCRIPTION= 
        ( ADDRESS=(PROTOCOL = TCP)(HOST = 192.168.11.101)(PORT = 1521))
        ( CONNECT_DATA= (SERVICE_NAME=orclpdb.oracle.com))
     )
    $ sqlplus scott/tiger@srv_pdb
    

    2017年4月8日土曜日

    VirtualBox でホストマシンのディレクトリ参照(共有)

    インストールパッケージなどをホストマシンで解凍し、仮想環境から参照すると便利である。
    vboxsf グループに利用ユーザを加入しないと参照できなので注意が必要である。




    1.「共有フォルダー」を選択


    2.「+」でフォルダー追加


    3.フォルダーのプルダウン選択


    4.フォルダーを指定


    5.フォルダーの自動マウントを指定


    6.自動マウントで指定のフォルダが追加されているのを確認

    7.利用ユーザを vboxsf グループに加入
    # su - oracle
    $ id
    uid=1200(oracle) gid=54321(oinstall) groups=54321(oinstall),54322(dba),54323(oper),54324(backupdba),54325(dgdba),54326(kmdba),54327(racdba)
    $ ls -l /media/sf_share/
    ls: ディレクトリ '/media/sf_share/' を開くことが出来ません: 許可がありません
    $ exit
    ログアウト
    # cp /etc/group /etc/group.bk
    # gpasswd -a oracle vboxsf
    ユーザ oracle をグループ vboxsf に追加
    # diff /etc/group.bk /etc/group
    73c73
    < vboxsf:x:999:inst12c
    ---
    > vboxsf:x:999:inst12c,oracle
    # su - oracle
    oracle@vbox-win10:~$ ls -l /media/sf_share/
    合計 0
    drwxrwx--- 1 root vboxsf 0  4月  2 02:41 oracle12c
    

    ubuntu 上の oracle 12cにjava で接続確認

    ubuntu 上のoracle12c へ java プログラムから接続確認する。




    1.サンプルプログラム
    import java.sql.*;
    
    class sample01 {
      public void tblslt() throws Exception {
        String user = "scott";
        String pass = "tiger";
        String server = "localhost";
        String sid = "orcl";
    
        Connection conn = null;
        Statement  stmt = null;
        ResultSet  rset = null;
    
        Class.forName("oracle.jdbc.driver.OracleDriver");
        conn = DriverManager.getConnection(
               "jdbc:oracle:thin:@" + server + ":1521:" + sid,user,pass);
        stmt = conn.createStatement();
        rset = stmt.executeQuery("select deptno,dname,loc from dept");
        while(rset.next()) {
          System.out.printf("deptno = [%s]\n",rset.getString(1));
          System.out.printf("dname  = [%s]\n",rset.getString(2));
          System.out.printf("loc    = [%s]\n",rset.getString(3));
        }
        conn.close();
      }
    
      public static void main(String args[]) throws Exception {
        sample01 obj = new sample01();
        obj.tblslt();
      }
    }
    
    2.コンパイルと実行
    $ ls -l
    合計 8
    -rw-rw-r-- 1 inst12c inst12c 902  3月 29 16:03 sample01.java
    $ javac sample01.java 
    $ ls -l
    合計 16
    -rw-r--r-- 1 inst12c ibst12c 1763  3月 29 16:04 sample01.class
    -rw-rw-r-- 1 ibst12c ibst12c  902  3月 29 16:03 sample01.java
    $ java -classpath $ORACLE_HOME/jdbc/lib/ojdbc6.jar:. sample01
    deptno = [10]
    dname  = [ACCOUNTING]
    loc    = [NEW YORK]
    deptno = [20]
    dname  = [RESEARCH]
    loc    = [DALLAS]
    deptno = [30]
    dname  = [SALES]
    loc    = [CHICAGO]
    deptno = [40]
    dname  = [OPERATIONS]
    loc    = [BOSTON]
    

    ubuntu 上の oracle 12cで Pro*c コンパイル

    ubuntuにoracle をインストールした直後の状態から Pro*c のコンパイルを通すには幾つか設定が必要である。




    1.動作確認のために使用したPrco*Cプログラム
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sqlca.h>
    /*
    SQL> desc dept
     名前                                    NULL?    型
     ----------------------------------------- -------- ----------------------------
     DEPTNO                                    NOT NULL NUMBER(2)
     DNAME                                              VARCHAR2(14)
     LOC                                                VARCHAR2(13)
    */
    struct {
      char deptno[2+1];
      char dname[14+1];
      char loc[13+1];
    } rec;
    
    void
    main(argc,argv)
    int argc;
    char *argv[];
    {
      char *sp_uid = "scott/tiger";
    
      EXEC SQL CONNECT :sp_uid;
    
      EXEC SQL DECLARE CUR_SCOTT CURSOR FOR
      SELECT DEPTNO,DNAME,LOC FROM DEPT;
      EXEC SQL OPEN CUR_SCOTT;
    
      while(1) {
        EXEC SQL FETCH CUR_SCOTT INTO :rec;
    
        if (sqlca.sqlcode == 1403) {
          break;
        }
    
        printf("DEPTNO = [%s]\n",rec.deptno);
        printf("DNAME  = [%s]\n",rec.dname);
        printf("LOC    = [%s]\n",rec.loc);
      }
    }
    

    2.$ORACLE_HOME/precomp/admin/pcscfg.cfg を環境に合わせて調整
      
    $ vi $ORACLE_HOME/precomp/admin/pcscfg.cfg
    =======================================================================
    diff pcscfg.cfg.org pcscfg.cfg
    1c1
    < sys_include=($ORACLE_HOME/precomp/public,/usr/include,/usr/lib/gcc-lib/x86_64-redhat-linux/3.2.3/include,/usr/lib/gcc/x86_64-redhat-linux/4.1.1/include,/usr/lib64/gcc/x86_64-suse-linux/4.1.0/include,/usr/lib64/gcc/x86_64-suse-linux/4.3/include)
    ---
    > sys_include=($ORACLE_HOME/precomp/public,/usr/include,/usr/include/x86_64-linux-gnu,/usr/lib/gcc/x86_64-linux-gnu/6.2.0/include)
    =======================================================================
    

    3.LD_LIBRARY_PATHを設定
    export LD_LIBRARY_PATH=$ORACLE_HOME/lib
    
    • $ORACLE_HOME/lib配下には、ubuntu のデフォルトライブラリと重複するライブラリがあるため、 ウインドウマネージャを使用するアカウントや、ライブラリ更新などを行うアカウントの .profile などに登録すると干渉起こす場合がある。オラクル関連のアプリをコンパイル、起動する際に 設定するか、専用のアカウントで使用するのがよいと思われる。

    4.コンパイル用Makefile (procオプションのコード生成は"ANSI_C"とする)
    PROGRAM = sample01
    OBJS    = sample01.o
    CC      = gcc
    PROC    = proc
    PFLAGS  = include=$(ORACLE_HOME)/precomp/public
    PFLAGS += include=$(ORACLE_HOME)/rdbms/public
    PFLAGS += include=.
    PFLAGS += CODE=ANSI_C
    #PFLAGS += CODE=CPP
    
    CFLAGS  = -O3 -trigraphs -fPIC -DPRECOMP
    CFLAGS += -I$(ORACLE_HOME)/precomp/public
    CFLAGS += -I$(ORACLE_HOME)/rdbms/public
    CFLAGS += -I$(ORACLE_HOME)/plsql/public
    CFLAGS += -I$(ORACLE_HOME)/network/public
    CFLAGS += -I.
    CFLAGS += -DLINUX -DORAX86_64 -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1
    CFLAGS += -D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT
    CFLAGS += -DNS_THREADS -DLONG_IS_64 -DSS_64BIT_SERVER -DLDAP_CM -m64
    LDFLAGS = -L$(ORACLE_HOME)/lib -lclntsh -lsql12 -L $(ORACLE_HOME)/precomp/lib -lproc2 -lm
    
    .SUFFIXES: .c .o
    .SUFFIXES: .pc .c
    
    $(PROGRAM):$(OBJS)
     $(CC) $^ -o $@ $(LDFLAGS)
    
    .c.o:
     $(CC) $(CFLAGS) -c $<
    
    .pc.c:
     $(PROC) iname=$* $(PFLAGS)
    
    clean:
    

    5.コンパイルと実行
    $ ls -l
    合計 16
    -rw-r--r-- 1 naoki naoki 904  3月 29 15:24 Makefile
    -rw-r--r-- 1 naoki naoki 854  3月 29 15:24 sample01.pc
    $ make
    proc iname=sample01 include=/u01/app/oracle/product/11.2.0/dbhome_1/precomp/public include=/u01/app/oracle/product/11.2.0/dbhome_1/rdbms/public include=. CODE=ANSI_C
    
    Pro*C/C++: Release 11.2.0.1.0 - Production on 水 3月 29 15:33:04 2017
    
    Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.
    
    システムのデフォルト・オプション値: /u01/app/oracle/product/11.2.0/dbhome_1/precomp/admin/pcscfg.cfg
    
    gcc -O3 -trigraphs -fPIC -DPRECOMP -I/u01/app/oracle/product/11.2.0/dbhome_1/precomp/public -I/u01/app/oracle/product/11.2.0/dbhome_1/rdbms/public -I/u01/app/oracle/product/11.2.0/dbhome_1/plsql/public -I/u01/app/oracle/product/11.2.0/dbhome_1/network/public -I. -DLINUX -DORAX86_64 -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT -DNS_THREADS -DLONG_IS_64 -DSS_64BIT_SERVER -DLDAP_CM -m64 -c sample01.c
    gcc sample01.o -o sample01 -L/u01/app/oracle/product/11.2.0/dbhome_1/lib -lclntsh -lsql11 -L /u01/app/oracle/product/11.2.0/dbhome_1/precomp/lib -lproc2 -lm
    rm sample01.c
    $ ls -l
    合計 48
    -rw-r--r-- 1 inst12c inst12c   904  3月 29 15:24 Makefile
    -rwxr-xr-x 1 inst12c inst12c 12928  3月 29 15:33 sample01
    -rw-r--r-- 1 inst12c inst12c     0  3月 29 15:33 sample01.lis
    -rw-r--r-- 1 inst12c inst12c  4552  3月 29 15:33 sample01.o
    -rw-r--r-- 1 inst12c inst12c   854  3月 29 15:24 sample01.pc
    $ sample01
    DEPTNO = [10]
    DNAME  = [ACCOUNTING    ]
    LOC    = [NEW YORK     ]
    DEPTNO = [20]
    DNAME  = [RESEARCH      ]
    LOC    = [DALLAS       ]
    DEPTNO = [30]
    DNAME  = [SALES         ]
    LOC    = [CHICAGO      ]
    DEPTNO = [40]
    DNAME  = [OPERATIONS    ]
    LOC    = [BOSTON       ]
    

    oracle 12c が要求する各種設定を一括設定

    ubuntu16.10 にoracle12cをインストールするのに必要な各種設定を纏めたスクリプト(12.1.0.2.0、12.2.0.1.0共用)である。
    ※インストール手順については 「ubuntuにoracle12c(12.2.0.1.0) をインストール」 を参照



    #! /bin/sh
    
    # 
    PKG="libaio1"
    PKG="$PKG libaio-dev"
    PKG="$PKG sysstat"
    
    # PKG="gawk"
    # PKG="$PKG rpm"
    # PKG="$PKG libtool"
    # PKG="$PKG expat"
    # PKG="$PKG alien"
    # PKG="$PKG ksh"
    # PKG="$PKG unixodbc"
    # PKG="$PKG unixodbc-dev"
    # PKG="$PKG elfutils"
    # PKG="$PKG libelf-dev"
    # PKG="$PKG default-jre"
     
    #
    apt-get install $PKG
    
    #
    ln -sf /bin/bash /bin/sh
    ln -s  /usr/bin/awk /bin/awk
    ln -s  /usr/lib/x86_64-linux-gnu /usr/lib64
    ln -s  /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib64
    
    # ln -s  /usr/bin/rpm /bin/rpm
    # ln -s  /usr/bin/basename /bin/basename
    
    #
    groupadd -g 54321 oinstall
    groupadd -g 54322 dba
    groupadd -g 54323 oper
    groupadd -g 54324 backupdba
    groupadd -g 54325 dgdba
    groupadd -g 54326 kmdba
    groupadd -g 54327 racdba
    useradd -u 1200                                  \
            -g oinstall                              \
            -G dba,oper,backupdba,dgdba,kmdba,racdba \
            -d /home/oracle                          \
            -m oracle
    
    #
    mkdir -p /u01/app/oracle
    chown -R oracle:oinstall /u01/app
    chmod -R 775 /u01
    
    #
    cat <<EOF >> /etc/security/limits.conf
    #
    oracle soft nproc   2047
    oracle hard nproc  16384
    oracle soft nofile  1024
    oracle hard nofile 65536
    oracle soft stack  10240
    EOF
    
    #
    cat <<EOF >> /etc/sysctl.conf
    #
    fs.aio-max-nr=1048576
    fs.file-max=6815744
    kernel.shmall=2097152
    kernel.shmmni=4096
    kernel.sem=250 32000 100 128
    net.ipv4.ip_local_port_range=9000 65500
    net.core.rmem_default=262144
    net.core.rmem_max=4194304
    net.core.wmem_default=262144
    net.core.wmem_max=1048586
    kernel.shmmax=1073741824
    EOF
    
    #
    sysctl -p
    

    ubuntuの oracle 12c (12.2.0.1.0) DB作成

    ubuntu16.10 上の oracle12c(12.2.0.1.0) におけるDB作成は、oracle12cダウンロードサイトのDB作成ドキュメントに従い、PDBにサンプルスキーマ(scott)の作成した。
    ※インストール前準備などは 「ubuntuにoracle12c(12.2.0.1.0) をインストール」を参照



    1.DB作成

    url: http://www.oracle.com/technetwork/jp/database/enterprise-edition/documentation/index.html



    2.サンプルスキーマ(scott)を作成

    DB作成手順の最後に作成した PDB 用のNet サービス名で接続してサンプルスキーマを作成。

    $ cd $ORACLE_HOME/rdbms/admin
    $ vi utlsampl.sql
    ================================================
    36c36
    < CONNECT SCOTT/tiger
    ---
    > CONNECT SCOTT/tiger@srv_pdb
    ================================================
    $ sqlplus system/passwd@srv_pdb
    SQL> @?/rdbms/admin/utlsampl.sql
    $ sqlplus scott/tiger@srv_pdb
    SQL> select table_name from user_tables;
    
    TABLE_NAME
    --------------------------------------------------------------------------------
    DEPT
    EMP
    BONUS
    SALGRADE
    
    SQL> quit
    

    ubuntuに oracle 12c (12.2.0.1.0) をインストール

    oracle12c(12.2.0.1.0)は、12.1.0.2.0 のインストール時に発生していた各種エラーが解消され、ほとんどそのままインストールできるようである。

    ubuntu18.04 では、暫くの間 libpthread_nonshared.a が配布されず動かせなかったが、18.04.2からは配布されるようになりインストール可能になっている。しかし、18.04.2 では$ORACLE_HOME/bin/oracleが起動しないため、$ORACLE_HOME/lib/stubs 配下のライブラリを消去後 relink して再作成すると動作している。

    18.10、19.04 では、libpthread_nonshared.a が配布されていない。



    1.事前準備として以下の構成のディレクトリを作成
     /mnt/vbox/share/oracle12c 
     |-- database : linuxx64_12201_database.zip を展開
     `-- inst12c : inst12c.tar.gz を展開
    

    2.oracle12c が要求する各種設定を適用
    $ sudo -s
    # cd /mnt/vbox/share/oracle12c/inst12c
    # ./inst12c.sh
    

    ※inst12c.sh の内容は、 「oracle12c が要求する各種設定を一括設定」 を参照

    3.oracle12c のインストール
    # cd /mnt/vbox/share/oracle12c/database/install
    # cp /usr/bin/unzip .
    # passwd oracle
    Changing password for user oracle.
    New UNIX password: <oracle ユーザーパスワード>
    Retype new UNIX password: <oracle ユーザーパスワード>
    passwd: all authentication tokens updated successfully.  
    # xhost +
    # su - oracle
    $ cd /mnt/vbox/share/oracle12c/database
    $ ./runInstaller
    $ exit
    # /u01/app/oraInventory/orainstRoot.sh
    # /u01/app/oracle/product12.2.0/dbhome_1/root.sh
    # su - oracle
    

    5.リスナとデータベース作成の前準備
     $HOME/.profile に以下の行を追記
    export ORACLE_BASE=/u01/app/oracle
    export ORACLE_HOME=$ORACLE_BASE/product/12.2.0/dbhome_1
    export ORACLE_SID=orcl
    export PATH=$ORACLE_HOME/bin:$PATH
    export NLS_LANG=JAPANESE_JAPAN.UTF8
    

    6.リスナの作成
    $ source .profile
    $ netca
    

    7.データベースの作成(サンプルスキーマ作成を含む)
    ==== ubuntu 18.04 では以下の手順が必要 ====
    $ cd $ORACLE_HOME/lib/stubs
    $ rm libc*
    $ cd ../../bin
    $ relink all
    $ dbca
    ===========================================
    
    
     ※上記実行時のメニュー選択は 「ubuntuのoracle12c(12.2.0.1.0) DB作成」 を参照

    8.データベース、リスナの起動、終了

     ※作成中

    9.オラクルクライアントのインストール

     ※「ubuntu に oracle client をインストール」を参照

    10.プログラムからのデータベース接続

    ubuntuに oracle 12c (12.1.0.2.0) をインストール

    サポート対象外ではあるが、ubuntu16.10 に oracle12c(12.1.0.2.0) をインストールする際、以下のようなエラーが発生する。
    /usr/bin/ld: /u01/app/oracle/product/12.1.0/dbhome_1/lib//libpls12.a(plzsql.o): relocation R_X86_64_32 against`.rodata.str1.4' can not be used when making a shared object。 -fPIC を付けて再コンパイルしてください。
    /usr/bin/ld: 最終リンクに失敗しました: 出力に対応するセクションがありません
    

    このエラーには、該当箇所に -no-pie オプションを付与することで解決した。
    ※このエラーについては、「Ubuntu 16 で Stack + GHC がライブラリのリンクに失敗する場合の対処法」 を参照させて頂いた。

    省力化のため、この問題も含めインストール中に出るエラーの対策をまとめた patch と oracle12c(12.1.0.2.0) をインストールする前準備のシェルを作成した。 なお、この手順は VirtualBox に ubuntu16.10 をインストールし、2017/03/19日時点までの update を当てておこなった。



    1.事前準備として以下の構成のディレクトリを作成
     /mnt/vbox/share/oracle12c 
     |-- database : linuxamd64_12102_database_[12]of2.zip を展開
     `-- inst12c : inst12c.tar.gz を展開
    

    2.oracle12c が要求する各種設定を適用
    $ sudo -s
    # cd /mnt/vbox/share/oracle12c/inst12c
    # ./inst12c.sh
    

    ※inst12c.sh の内容は、 「oracle12c が要求する各種設定を一括設定」 を参照

    3.oracle12c のインストール
    # cd /mnt/vbox/share/oracle12c/database/install
    # cp /usr/bin/unzip .
    # passwd oracle
    Changing password for user oracle.
    New UNIX password: <oracle ユーザーパスワード>
    Retype new UNIX password: <oracle ユーザーパスワード>
    passwd: all authentication tokens updated successfully.  
    # xhost +
    # su - oracle
    $ cd /mnt/vbox/share/oracle12c/database
    $ ./runInstaller -jreloc /usr/lib/jvm/default-java
    
    4.エラーが発生したら patch を適用
    $ cd /u01/app/oracle/product/12.1.0/dbhome_1
    $ patch -p1 -d . < /mnt/vbox/share/oracle12c/inst12c/ora12c_12.1.0.2.0-ubuntu.patch
    <再施行>
    $ exit
    # /u01/app/oraInventory/orainstRoot.sh
    # /u01/app/oracle/product12.1.0/dbhome_1/root.sh
    # su - oracle
    



    5.リスナとデータベース作成の前準備
     $HOME/.profile に以下の行を追記
    export ORACLE_BASE=/u01/app/oracle
    export ORACLE_HOME=$ORACLE_BASE/product/12.1.0/dbhome_1
    export ORACLE_SID=orcl
    export PATH=$ORACLE_HOME/bin:$PATH
    export NLS_LANG=JAPANESE_JAPAN.UTF8
    

    6.リスナの作成
    $ vi `which netca`
    ===========================================================
    diff bin.org/netca bin/netca
    95c95,96
    < JRE_DIR=/u01/app/oracle/product/12.1.0/dbhome_1/jdk/jre
    ---
    > #JRE_DIR=/u01/app/oracle/product/12.1.0/dbhome_1/jdk/jre
    > JRE_DIR=/usr/lib/jvm/default-java
    ===========================================================
    $ netca
    
     ※リスナー作成時のメニュー選択は1521ポートを使用するのであれば全てリターンで作成可

    7.データベースの作成
    $ vi `which dbca`
    ===========================================================
    diff bin.org/dbca bin/dbca
    70c70,71
    < JRE_DIR=/u01/app/oracle/product/12.1.0/dbhome_1/jdk/jre
    ---
    > #JRE_DIR=/u01/app/oracle/product/12.1.0/dbhome_1/jdk/jre
    > JRE_DIR=/usr/lib/jvm/default-java
    ===========================================================
    $ dbca
    

    8.データベース、リスナの起動、終了

     ※作成中


    9.オラクルクライアントのインストール

     ※「ubuntu に oracle client をインストール」を参照

    10.プログラムからのデータベース接続

    2017年4月7日金曜日

    oracle 11g が要求する各種設定を一括設定

    ubuntu16.10 にoracle11gをインストールするのに必要な各種設定を纏めたスクリプトである。(ubuntu16.04でも同様にンストール可能であった)
    ※インストール手順については 「ubuntuに oracle11g をインストール」 を参照



    1.rootユーザにて以下のシェル実行
    #! /bin/sh
    
    #
    apt-get install gawk rpm libaio1 libaio-dev libtool expat alien ksh unixodbc unixodbc-dev sysstat elfutils libelf-dev default-jre # libstdc++5
    
    ln -sf /bin/bash /bin/sh
    ln -s /usr/bin/awk /bin/awk
    ln -s /usr/bin/rpm /bin/rpm
    ln -s /usr/bin/basename /bin/basename
    ln -s /usr/lib/x86_64-linux-gnu /usr/lib64
    ln -s /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib64
    
    # add ubuntu16.10
    ln -s /usr/lib/x86_64-linux-gnu/libpthread_nonshared.a /usr/lib64
    ln -s /usr/lib/x86_64-linux-gnu/libc_nonshared.a /usr/lib64
    ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6 /usr/lib64
    
    #
    mkdir /etc/rc.d
    ln -s /etc/rc0.d /etc/rc.d/rc0.d
    ln -s /etc/rc1.d /etc/rc.d/rc1.d
    ln -s /etc/rc2.d /etc/rc.d/rc2.d
    ln -s /etc/rc3.d /etc/rc.d/rc3.d
    ln -s /etc/rc4.d /etc/rc.d/rc4.d
    ln -s /etc/rc5.d /etc/rc.d/rc5.d
    ln -s /etc/rc6.d /etc/rc.d/rc6.d
    ln -s /etc/rcS.d /etc/rc.d/rcS.d
    
    #
    groupadd -g 54321 oinstall
    groupadd -g 54322 dba
    groupadd -g 54323 oper
    groupadd -g 54324 backupdba
    groupadd -g 54325 dgdba
    groupadd -g 54326 kmdba
    useradd -u 1200                           \
            -g oinstall                       \
            -G dba,oper,backupdba,dgdba,kmdba \
            -d /home/oracle                   \
            -m oracle
    
    sudo mkdir -p /u01/app
    sudo chown -R oracle:oinstall /u01/app
    sudo chmod -R 775 /u01/app
    
    #
    REL_FILE=/etc/redhat-release
    echo "Red Hat Linux release 5" > $REL_FILE
    
    #
    cat <<EOF >> /etc/security/limits.conf
    #
    oracle soft nproc  2047
    oracle hard nproc  16384
    oracle soft nofile 1024
    oracle hard nofile 65536
    oracle soft stack  10240
    EOF
    
    #
    cat <<EOF >> /etc/sysctl.conf
    #
    fs.aio-max-nr=1048576
    fs.file-max=6815744
    kernel.shmall=2097152
    kernel.shmmni=4096
    kernel.sem=250 32000 100 128
    net.ipv4.ip_local_port_range=9000 65500
    net.core.rmem_default=262144
    net.core.rmem_max=4194304
    net.core.wmem_default=262144
    net.core.wmem_max=1048586
    kernel.shmmax=1073741824
    EOF
    
    #
    sysctl -p
    
    #
    mv $REL_FILE $REL_FILE.bk