シェルスクリプトマガジン

香川大学SLPからお届け!(Vol.58掲載)

著者:竹原 一駿
2018年秋に広島と香川で「オープンソースカンファレンス」(OSC)が開催されました。SLPは、両OSCでブースを出展し、OSC香川では3人の学生がライトニングトーク(LT)を行いました。今回は、これらの活動の内容や、それによって得られた体験などについて報告します。OSCへの一般参加や出展などを考えている読者の方の参考になれば幸いです。

シェルスクリプトマガジン Vol.58は以下のリンク先でご購入できます。

図2 自作コンテナエンジンのソースコードの一部
unshareシステムコールによるLinux Namespaceの分離
unshare(
  CloneFlags::CLONE_NEWPID
    | CloneFlags::CLONE_NEWIPC
    | CloneFlags::CLONE_NEWUTS
    | CloneFlags::CLONE_NEWNS
    | CloneFlags::CLONE_NEWUSER,)
fork/execシステムコールによるコンテナ内子プロセス生成
match fork() {
  Ok(ForkResult::Parent { child, .. }) => {
    match waitpid(child, None).expect("waitpid faild") {
      WaitStatus::Exited(_, _) => {}
      WaitStatus::Signaled(_, _, _) => {}
      _ => eprintln!("Unexpected exit."),
    }
  }
  Ok(ForkResult::Child) => {
    sethostname(&self.name).expect("Could not set hostname");
    fs::create_dir_all("proc").unwrap_or_else(|why| {
      eprintln!("{:?}", why.kind());
    });
    println!("Mount procfs ... ");
    mounts::mount_proc().expect("mount procfs failed.");
    let cmd = CString::new(self.command.clone()).unwrap();
    let default_shell = CString::new("/bin/bash").unwrap();
    let shell_opt = CString::new("-c").unwrap();
    execv(&default_shell, &[default_shell.clone(), shell_opt, cmd]).expect("execution faild.");
  }
  Err(_) => eprintln!("Fork failed"),
}
図5 「数字に隠された真実」のソースコードの一部
数値を1桁ずつ分解して、すべての和を求める関数
function add_1(number, result_text, c) {
  var num = [];
  if (parseInt(number / 10) == 0 && (number != 6 || number != 9)) { return 0; } // 1桁になって悪魔の数字じゃなければ失敗
  num = num_split_onedigit(number); // 数値を1桁ずつ分解
  sum = num_add_onedigit(num); // すべて加算
  result_text[c] = array_value_text(num, sum, "+"); // 計算過程の文字列を作成
  var check = akumanumber_check(sum, result_text); // 悪魔の数字かどうかチェック
  if (check != 0) { return check; } // 悪魔の数字なら終了
  var result = add_1(sum, result_text, c + 1); // 処理1を実行(再帰)
  if (result != 0) { return result; } else { result_t  ext.splice(c, 1); }
  var result = mult_1(sum, result_text, c + 1); // 処理2を実行(相互再帰)
  if (result != 0) { return result; } else { result_text.splice(c, 1); }
  return 0;
}
数値を1桁ずつ分解して、すべての積を求める関数
function mult_1(number, result_text, c) {
  var num = [];
  if (parseInt(number / 10) == 0 && (number != 6 || number != 9)) { return 0; } // 1桁になって悪魔の数字じゃなければ失敗
  num = num_split_onedigit(number); // 数値を1桁ずつ分解
  sum = num_mult_onedigit(num); // すべて乗算
  result_text[c] = array_value_text(num, sum, "×"); // 計算過程の文字列を作成
  var check = akumanumber_check(sum, result_text); // 悪魔の数字かどうかチェック
  if (check != 0) { return check; } // 悪魔の数字なら終了
  var result = add_1(sum, result_text, c + 1); // 処理1を実行(相互再帰)
  if (result != 0) { return result; } else { result_text.splice(c, 1); }
  var result = mult_1(sum, result_text, c + 1); // 処理2を実行(再帰)
  if (result != 0) { return result; } else { result_text.splice(c, 1); }
  return 0;
}
図9 サーバー監視システムのソースコードの一部
int SystemAnalyzer::GetPreTick_(void)
{
  // 演算に使用されたTick値を取得
  FILE *infile = fopen("/src/proc/stat", "r");
  if (NULL == infile) {
    cout << "[GetCPUUsage]<<Cannot open /src/proc/stat"
         << endl;
    return 0;
  }
  int usr, nice, sys;
  char buf[1024]; // 文字列"cpu"の部分の入力用
  int result = fscanf(infile, "%s %d %d %d",
                      buf, &usr, &nice, &sys);
  if (result == -1) {
    cout << "[GetCPUUsage]<<Cannot read fscanf"
         << endl;
    return 0;
  }
  fclose(infile);
  return usr + nice + sys;
}