over 3 years ago

Array vs Object

許多人常常會搞不清楚array與object的差別,在使用上也常常的混著用,我們先來探討實際上的差異

先看一個example:

var alpha_array = ['a','b','c','d'];
var alpha_object = {0:'a',1:'b',2:'c',3:'d'};

alpha_arrayalpha_object會產生相似的效果,都是包含四個屬性,具有相同的key-value,操作的方式也類似

console.log(alpha_array[0]);//a

console.log(alpha.object[0]);//a

但是兩者仍有十分明顯的差異,alpha_array卻是繼承自Array.protopyte,而alpha_object繼承自Object.prototype, 所以alpha_array會擁有Array該有的method,舉例來說: length

console.log(alpha_array.length); // 4  

console.log(alpha_object.length); // undefined

好,那我們該如何知道某個物件是屬於array還是object? 只透過typeof不可行,因為兩者回傳的皆為object

console.log(typeof alpha_array);// object  

console.log(typeof alpha_object);// object

必須再透過constructor的來進行確認

console.log(alpha_array.constructor === Array);// true

console.log(alpha_object.constructor === Array);// false

於是我們可以透過以下的方法來確定是否屬於array

function isArray(value){  
    return typeof value === 'object' && value.constructor === Array;
}

以下是Javascript: The Good Parts中,作者所提供的陣列偵測方法

function isArray(value){
    return value &&  
        typeof value === 'object' &&  
        typeof value.length === 'number' &&  
        typeof value.splice === 'function' &&  
        !(value.propertyIsEnumerable('length'));  
}

Array Element Deletion

透過delete

因為array其實也是object,所以可以透過delete來刪除陣列內的元素

var arr = ['a','b','c','d','e'];  
delete arr[1];
console.log(arr);// ['a',undefined,'c','d','e']

console.log(arr.length);// 5

從上面的例子中可以發現,被delete的元素會變成undefined,所以length並不會改變

透過splice

array.slice([begin[, end]]),begin為欲刪除的開始位置,end為欲刪除的元素數量

var arr = ['a','b','c','d','e'];  
arr.splice(1,1);
console.log(arr);// ['a','c','d','e']

console.log(arr.length);// 4

Array Dimension

js中沒有超過一個維度的陣列,但同c/c++語言,陣列內的元素也可以是陣列

var matrix = [
    [0,1,2],
    [3,4,5],
    [6,7,8]
];
console.log(matrix[1,1]);// 4

以上程式也可以寫為

var matrix = [];
var row = 3, col = 3 ;
for (var i = 0; i < row; i++){
    matrix[i] = [];
    for(var j = 0; j < col; j++){
        matrix[i][j] = i * row + j;
    }
}
 
over 3 years ago

Closure

能將外部函式的變數關到內部函式,用途是延續外部變數的生命

var Car = function(){
  var price = 1000;
  //閉包, 將price關在裡面

  function getPrice(){
    return price;
  };
  //閉包, 將price關在裡面

  function addPrice(p){
    price = price + p;
  };
  //回傳上述定義的closure function

  return {getPrice:getPrice,addPrice:addPrice};
};

var car = Car();
/*
此時Car()已經被執行完畢,並且回傳getPrice/addPrice給car  
所以price的生命週期已經結束了,但是我們透過closure把price關在裡面,延續了price的生命週期
*/
console.log(car.getPrice()); //print 1000

car.addPrice(1000);
console.log(car.getPrice()); //print 2000

有了閉包的概念後,我們接下來要了解,閉包所關起來的是變數的reference,而不是變數的value,這非常重要!

假設有個Array FA,我們預期FA[0]()會得到alert(0), FA[1]()會得到alert(1)

先看一個失敗的範例

var FA = [];//定義一個FA array

for(var i=0;i<5;i++){
    //將function指派給FA,透過閉包的方式將i關進去

    FA[i] = function(){
    alert(i);
  };
}  
FA[0]();//得到alert(5)

因為閉包是直接取用外部的變數reference而不是value,在for迴圈中結束後得到i=5,所以閉包中的i全部都是5

正確的範例

var FA = [];//定義一個FA array

for(var i=0;i<5;i++){
  //我們透過立刻執行函式的方式,將i在第一時間馬上綁入

    FA[i] = function(k){
    //透過return來回傳實際上要執行的函式

    return function(){
        alert(k);
    };   
  }(i);
}  
FA[0]();//得到alert(0)
 
over 3 years ago

以下是survey官網的tutorial後整理的心得,是有關於this.props以及如何透過props存取parent傳入的data

1. pros and component properties

先想一個問題,child node要如何得到parent node的data

例如CommentList包含Comment,那麼Comment要如何得到CommentList的data?

var CommentList = React.createClass({
  render: function() {
    return (
      <div className="commentList">
        <Comment author="Pete Hunt">Good!</Comment>
      </div>
    );
  }
});

可以看到在CommentList中,我們替Comment這個element建立了author的attribute與Good!這個comment text,那麼我們如何在Comment中獲得這兩個data?

這時我們就需要透過this.props來進行存取

var Comment = React.createClass({
  render: function() {
    return (
      <div className="comment">
        <h2 className="commentAuthor">
          //透過this.props.author來得到 author="Pete Hunt" 的 "Pete Hunt"

          {this.props.author}
        </h2>
           //透過this.props.children來得到 comment text "Good!"

          {this.props.children}
      </div>
    );
  }
});

2. Hook the data

先再看一次 CommentList

var CommentList = React.createClass({
  render: function() {
    return (
      <div className="commentList">
        <Comment author="Pete Hunt">Good!</Comment>
      </div>
    );
  }
});

如果我們想要動態載入 <Comment author="Pete Hunt">Good!</Comment> ,比如說從server將資料fetch下來後再render,而不是一開始就在code刻死,該怎麼做?

我們先假設我們從server fetch下來的data如下

var data = [
  {author: "Pete Hunt", text: "This is one comment"},
  {author: "Jordan Walke", text: "This is *another* comment"}
];

然後把握一個原則,data會由parent往child傳,所以我們要先從最上面的parent往下丟

假設整個structure為CommentBox -> CommentList -> Comment

Step 1: 將data傳進去CommentBox

React.render(
  <CommentBox data={data} />,
  document.getElementById('content')
);

Step2: 現在data已經進入CommentBox了,我們要在CommentBox中透過props來接它

var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        //利用this.props.data來接

        <CommentList data={this.props.data} />
        <CommentForm />
      </div>
    );
  }
});

Step3: 很好,我們繼續往下一層的CommentList傳,並且把它render出來。這邊可能會有點複雜

var CommentList = React.createClass({
  render: function() {
    //透過this.props.data.map來將data的內容一個一個讀出來

    var commentNodes = this.props.data.map(function (comment) {
      return (
        <Comment author={comment.author}>
          {comment.text}
        </Comment>
      );
    });
    return (
      <div className="commentList">
        {commentNodes}
      </div>
    );
  }
});

我們看一下為何要this.props.data.map?

如果還有印象,我們所假設的data有兩筆,而透過map可以一筆一筆讀出來,可以想成for-each

所以,我們就可以透過

 var commentNodes = this.props.data.map(function (comment) {
      return (
        <Comment author={comment.author}>
          {comment.text}
        </Comment>
      );
    });

來將data傳給最內部的Comment了! 最後再把它render出來即可

謹記在心,props 是從parent傳進來的,而且為immutable

 
over 3 years ago

我們可以透過此API來存取裝置的acceleration, rotation rateorientation
但要注意的是,目前各家browser的支援度與計算方式都不太相同

DeviceMotion & DeviceMotionEvent

https://developer.mozilla.org/en-US/docs/Web/Events/devicemotion
https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent

DeviceMotion.acceleration

回傳X,Y,Z三軸的加速度(m/s^2)

DeviceMotion.accelerationIncludingGravity

回傳考慮重力的X,Y,Z三軸的加速度(m/s^2)
將重力的資訊考慮進去的加速度結果,比如說一支平放在水平面上的手機
透過acceleration所得到的z會等於0
透過accelerationIncludingGravity所得到的z會大約等於重力加速度-9.8 (負號表示方向相反)
注意的是,若裝置沒有重力感測器,則回傳的結果會與acceleration相同

DeviceMotion.rotationRate

回傳 alpha, beta, gamma (degree per second)
rotationRate是計算各軸線的旋轉率,若是裝置無法提供此訊息,將會回傳 null
alpha 代表與螢幕垂直的軸線的旋轉率
beta 代表與螢幕平面 左->右 軸線的旋轉率
gamma 代表與螢幕平面 下->上 軸線的旋轉率

DeviceMotion.interval

回傳頻率的倒數,也就是每次獲取data的時間t (millisecond)

DeviceMotionEvent & Example

if (window.DeviceMotionEvent) {
    // Add listener

    window.addEventListener('devicemotion', deviceMotionHandler, false);
} else {
    console.log('DeviceMotionEvent not support');
}
function deviceMotionHandler(event)
{
  // Get the data

  var accel_X = event.acceleration.x;
  var accel_Y = event.acceleration.y;
  var accel_Z = event.acceleration.z;
  var accel_inc_gravity_X = event.accelerationIncludingGravity.x;
  var accel_inc_gravity_Y = event.accelerationIncludingGravity.y;
  var accel_inc_gravity_Z = event.accelerationIncludingGravity.z;
  var alpha = event.rotationRate.alpha;
  var beta = event.rotationRate.beta;
  var gamma = event.rotationRate.gamma;
  var timeInterval = event.interval;
}

DeviceOrientation & DeviceOrientationEvent

https://developer.mozilla.org/en-US/docs/Web/Events/deviceorientation
https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent

DeviceOrientaion.absolute

回傳 true/false
若是true,代表採用相對地球的絕對角度; 若是false,代表採用相對的角度

DeviceOrientaion.alpha

alpha代表Z軸的旋轉量 0 <= alpha <= 360 度

DeviceOrientaion.beta

beta代表X軸的旋轉量,裝置的前後動向(front-to-back) -180 <= beta <= 180 度

DeviceOrientaion.gamma

gamma代表Y軸的選轉量,裝置的左右動向(side-to-side) -90 <= gamma <= 90 度

DeviceOrientaion & Example

if (window.DeviceOrientationEvent){
    // Add listener

    window.addEventListener("deviceorientation", deviceOrientationHandler, false);
}else{
    $('#showMessage2').html("NOT support");
    console.log("DeviceOrientationEvent not support");
}
function deviceOrientationHandler(event)
{
  // Get data

  var alpha = event.alpha;
  var beta = event.beta;
  var gamma = event.gamma;
}
 
over 3 years ago

以下是由官方網站的Guide所整理出來 https://www.firebase.com/docs/web/guide/
本文是介紹web介面的使用方式,但是包含通用的Firebase資料操作方式

Install

<script src="https://cdn.firebase.com/js/client/2.2.4/firebase.js"></script>  

Understanding Data

1. It's a Json Tree !

資料並不是table/record,而是以json tree來實作

Example: 插入widgetusers/mchen裡面

{
    "users": {
    "mchen": {
        "friends": { "brinchen": true },
        "name": "Mary Chen",
        // our child node appears in the existing JSON tree

        "widgets": { "one": true, "three": true }
    },
    "brinchen": { ... },
    "hmadi": { ... }
    }
}
2. Creating Firebase Data Reference

要對data進行操作之前,要先建立data reference

var dataRef = new Firebase('https://docs-examples.firebaseio.com/web/data');  

建立之後,並不會馬上與server進行連線。Data都是在進行操作的同時,才會從server端Fetch下來

另外,也可以透過此方式直接Access child node,比如說要存取users/mchen/name 可以透過

var dataRef = new Firebase("https://docs-examples.firebaseio.com/web/data/users/mchen/name");  

或者你也可以使用他所提供的child() API來存取

var rootRef = new Firebase('https://docs-examples.firebaseio.com/web/data');  
rootRef.child('users/mchen/name');  
3. Arrays in Firebase

Firebase並不支援array的存取,實作上會用整數當成key

比如說我們傳 ['Hello','world']

Firebase會存成 {0: 'Hello', 1: 'world'}

但如果我們就是想要得到array,該怎辦?

在這個case下,如果user是用 val() 或是 Rest API 來要求data時

如果data滿足 All of the keys are integers, and more than half of the keys between 0 and the maximum key in the object have non-empty values

Firebase就會render array給user

// we send this

['a', 'b', 'c', 'd', 'e']  
// Firebase stores this  

{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}  

// since the keys are numeric and sequential,

// if we query the data, we get this

['a', 'b', 'c', 'd', 'e']

// however, if we then delete a, b, and d,  

// they are no longer mostly sequential, so  

// we do not get back an array  

{2: 'c', 4: 'e'}  
4. Limitations and Restrictions
Description Limit
Depth of child nodes 32
Length of a Key 768 bytes
Size of one child value 10 mb
Write from SDK 16 mb
Write from REST 256 mb
Nodes in a read operation 100 million

Saving Data

1. set()

set會將data存到特定的path,進行這個動作要非常小心,因為會override原本已經存在於該path的所有data

2. update()

如果要新增某個屬性到child,但不想要Overwrite其他的child node,這時候就可以使用update

3. push()

通常新增資料點會透過push來完成,比如說今天定義了/book那麼如果想在此node下新增資料點,就會透過push的方式來達成

var postsRef = dataRef.child("books");
  postsRef.push({
    author: "David",
    title: "New Magic Book"
  });
  postsRef.push({
    author: "Harry",
    title: "Harry Potter 5"
  });

每次push()後,Firebase都會基於timestamp來生成一個unique ID來代表每一個資料點,所以剛剛push的data會被存成

{
  "posts": {
    "-JRHTHaIs-jNPLXOQivY": {
        author: "David",
        title: "New Magic Book"
    },
    "-JRHTHaKuITFIhnj02kE": {
        author: "Harry",
        title: "Harry Potter 5"
    }
  }
}

我們可以透過key()來得到此ID

// Generate a reference to a new location and add some data using push()

var newPostRef = postsRef.push({
  author: "gracehop",
  title: "Announcing COBOL, a New Programming Language"
});

// Get the unique ID generated by push()

var postID = newPostRef.key();
4. Adding Completion callback

set,push與updata都可以透過callback來檢查data寫入的狀態

dataRef.set("I'm writing data", function(error) {
    //成功:return null, 失敗: return error

  if (error) {
    alert("Data could not be saved." + error);
  } else {
    alert("Data saved successfully.");
  }
});

Retrieving Data

1. Read Event Type
value
觸發時機: 當有資料新增或更新的時候
回傳結果: data snapshot,包含該位置的data與所有的child data

Value events are always triggered last and are guaranteed to contain updates from any other events which occurred before that snapshot was taken.

child_added
觸發時機: 當存在child node或新child node被加入的時候
回傳結果: data snapshot,包含該位置下的new child data

child_added與value不同的地方在於,value會回傳該path下的所有content,child_added第一次會回傳所有存在的childe node,接著就是有新的才回傳新的child node

child_changed
觸發時機: 當child node被修改的時候
回傳結果: data snapshot,包含該位置下的modified child data
child_removed
觸發時機: 當child node被刪除的時候
回傳結果: data snapshot,包含該位置下的deleted child data

Example

// Get a reference to our posts

var ref = new Firebase("https://docs-examples.firebaseio.com/web/saving-data/fireblog/posts");

// Attach an asynchronous callback to read the data at our posts reference

ref.on("value", function(snapshot) {
  console.log(snapshot.val());
}, function (errorObject) {
  console.log("The read failed: " + errorObject.code);
});
2. Detaching Callbacks

移除特定的event與對應的callback

ref.off("value", originalCallback);

一次移除某個event下所有對應的callback

ref.off("value");

移除所有event的callback

ref.off();
3. Reading Data once

如果你只想要讀一次data就好,也就是說callback只想到call一次

ref.once("value", function(data) {
  // do some stuff once

});
4. Querying Data

提供orderByChild(), orderByKey(), orderByValue(), or orderByPriority()等方法

1. Ordering by specified child key

Queries can only order by one key at a time.

var ref = new Firebase("https://dinosaur-facts.firebaseio.com/dinosaurs");
ref.orderByChild("height").on("child_added", function(snapshot) {
  console.log(snapshot.key() + " was " + snapshot.val().height + " meters tall");
});

若是有child沒有該key,會回傳null,且順序是在最前面

2. Ordering by key name
var ref = new Firebase("https://dinosaur-facts.firebaseio.com/dinosaurs");
ref.orderByKey().on("child_added", function(snapshot) {
  console.log(snapshot.key());
});
3. Ordering by value

data set:

{
  "scores": {
    "bruhathkayosaurus" : 55,
    "lambeosaurus" : 21,
    "linhenykus" : 80,
    "pterodactyl" : 93,
    "stegosaurus" : 5,
    "triceratops" : 22
  }
}
var scoresRef = new Firebase("https://dinosaur-facts.firebaseio.com/scores");
scoresRef.orderByValue().on("value", function(snapshot) {
  snapshot.forEach(function(data) {
    console.log("The " + data.key() + " dinosaur's score is " + data.val());
  });
});
 
over 3 years ago

The Class

Javascript是屬於prototype-based語言,並沒有C++/Java中的class敘述. Javascript使用function來定義classes.

//define a new class called Car

var Car = function() {}; 

The constructor 建構子

簡單來說,constructor就是在宣告物件時第一個被呼叫的method,通常被用來進行變數的初始化。Javascript中並不需要特別宣告constructor method,因為被定義class function中的action都會在物件被宣告時執行。基本上無需撰寫return,如果constructor有回傳值,那回傳值就會被當作最後名稱所參考的值

var Car = function() {  
    //以下就是constructor  

    console.log("The Car object created!");  
};  

The property

property代表的是物件屬性,this代表目前的object,在class內,會透過this.property來操作當前這個物件的屬性或方法;在class外,會透過objectname.property來操作

// Define class

var Car = function (carName){  
    //透過this.property來操作 

    this.carName = carName;  
    console.log("The Car object created!");  
};  
// Declare object  

var benz = new Car('BENZ');  
//透過objectname.property來操作

console.log('My car name is ' + benz.carName);

The method

method代表物件的方法,呼叫method的方式與property相同,定義的方法也一樣

// Define class

var Car = function (carName){  
    //透過this.property來操作 

    this.carName = carName;
    this.run = function(){  
        console.log(this.carName+' is running!');
    };
};  
// Declare object  

var benz = new Car('BENZ');  
//透過objectname.property來操作

benz.run();  

The prototype

剛剛我們在定義property與method時,都是直接定義在一開始的宣告裡面,其實也可以透過新增class的prototype property/method 的方式來定義

// Define class

var Car = function (carName){  
    if(carName!=null)  
        this.carName = carName;  
};  
//使用prototype來定義新的method

Car.prototype.run = function(){  
    console.log(this.carName+' is running!');
};  
//使用protopyte來定義新的property

Car.prototype.carName = "No-name";

// Declare object  

var benz = new Car('BENZ');  
benz.run();  
var mazda = new Car();  
mazda.run();  

執行結果:

BENZ is running!  
No-name is running!  

Inheritance 繼承

繼承也是OOP中非常重要的概念之一,javascript目前只支援單一繼承,關鍵字是Object.create

//Define parent class  

var Car = function (carName){  
    this.carName = carName;  
};  
Car.prototype.run = function(){  
    console.log(this.carName+' is running!');
};  

//Define child class  

/* Step 1. 先定義constructor */  
function Benz(carName,model){  
    //呼叫parent's constructor  

    Car.call(this,carName);
    //初始化child class的property  

    this.model = model;  
};  

/* Step 2. create "Benz.prototype object"來繼承Car.prototype */  
//using Object.create, NOT using 'new Car()'  

Benz.prototype = Object.create(Car.prototype);  
//現在我們已經繼承了Car的prototype,有了Car的方法與屬性,但我們要將constructor指向child class  

Benz.prototype.constructor = Benz;  

/* Step3. 新增child class自己的方法與屬性*/  
Benz.prototype.accerate = function(){  
    console.log(this.carName+' with model '+this.model+ ' is accerating!');  
};

//Define object  

var benz = new Benz('BENZ','c200');  
benz.run();//由Car繼承而來  

benz.accerate();//Benz特有的方法  
Reference

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript

You can visit https://github.com/iamgyz/javascript_oop_intro to download the sample code as well.
 
almost 4 years ago

本文為筆者閱讀透視C語言指標這本書中有關於陣列與指標章節後的小小整理

陣列與指標

指標能夠與現有的陣列一同使用,或是從stack中配置記憶體,再將配置的記憶體視為陣列使用,但要注意的是兩者並非完全相同

int vector[5] = {1,2,3,4,5};

int *ptr = vector;

pv是指向陣列中 "第一個元素的address" ,並非陣列本身!

透過以下方法,所取得的也是第一個元素的address

printf("%p\n", vector);

printf("%p\n, &vector[0]);

那麼,如果直接使用&vector,又代表什麼?

這種方式所代表的意義是 "指向整個陣列的指標",另外兩個代表的是"指向整數的指標"

int vector[5] = {1,2,3,4,5};  
printf("%p\n", vector);  //point to the element
printf("%p\n", &vector[0]); //point to the element
printf("%p\n", &vector); //point to the array

陣列與指標的差異

考慮以下的case

int vector[5] = {1,2,3,4,5};

int *ptr = vector;

  1. 產生的機器碼不同

    透過 vector[i]vector+i 所產生的機器碼並不相同,但結果一致

  2. sizeof對陣列與指向陣列的指標的運算結果不相同

    sizeof(vector) = 20; //4 * 5 = 20  
    sizeof(ptr) = 4; //一個指標的大小  
    
  3. 指標ptr是lvalue,表示能夠被賦值,而vector並不是,所以無法修改其數值。換句話說,由os指派給陣列的位址無法改變,而指標能夠透過指派的方式指向記憶體中不同的位置

Reference

透視C語言指標 P.85~87

 
almost 4 years ago

本篇記錄如何運行container內的openssh-server

Environment

Host: Ubuntu 14.04
Container: Ubuntu 14.04

Install ssh in container

apt-get install ssh

安裝並設定完成之後,別忘了要commit

Run

接著透過運行以下指令

sudo docker run -d -p 5566:22 my_ubuntu /usr/sbin/sshd -D

-d代表detach模式(與-t -i相反),會跑在background

Host的port 5566會映射到Container的port 22

現在想開幾個就可以開幾個啦,只要外部port不要相同就可了

guang@petlab-SZ77:~$ sudo docker run -d -p 5566:22 my_ubuntu /usr/sbin/sshd -D
e763688cdc2f75b25d10893cbeb7a9f232f93bf06764c87b85e82a856ca7b04d
guang@petlab-SZ77:~$ sudo docker run -d -p 5577:22 my_ubuntu /usr/sbin/sshd -D
3823d3716ce8b1e69011c70da1f60a515030e8411c8e9babec980d6e3f31762a
guang@petlab-SZ77:~$ sudo docker run -d -p 5588:22 my_ubuntu /usr/sbin/sshd -D
3e2d58dde25064fd9322762262003bc52876c2438899d306928d5a0b45a3bff9

可以用docker ps看目前container的state

guang@petlab-SZ77:/home$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
3e2d58dde250        my_ubuntu:latest    /usr/sbin/sshd -D   48 seconds ago      Up 47 seconds       0.0.0.0:5588->22/tcp   goofy_feynman
3823d3716ce8        my_ubuntu:latest    /usr/sbin/sshd -D   53 seconds ago      Up 52 seconds       0.0.0.0:5577->22/tcp   ecstatic_fermat
e763688cdc2f        my_ubuntu:latest    /usr/sbin/sshd -D   3 minutes ago       Up 3 minutes        0.0.0.0:5566->22/tcp   hungry_kirch

Stop

guang@petlab-SZ77:/home$ sudo docker stop 3e2 382 e763
3e2
382
e763
 
almost 4 years ago

Environment:

Ubuntu 14.04

Installation

這邊直接安裝Ubuntu maintain的版本

sudo apt-get update

sudo apt-get install docker.io

(注意: 是docker.io,docker是另外的KDE3/GNOME2 package)

完成後可以下sudo docker info確定是否安裝成功

Pull Image

docker hub download pre-build image

sudo docker pull base/archlinux

check一下剛剛pull回來的image

sudo docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
base/archlinux      2014.07.03          ea234cde99e6        5 months ago        282.9 MB
base/archlinux      2014.04.01          56c61f5c2920        5 months ago        293.3 MB
base/archlinux      latest              dce0559daa1b        5 months ago        282.9 MB

Run Container

sudo docker run -t -i base/archlinux:latest bash

(-t 表示terminal -i 表示 stdin 後面接要執行的image及tag 最後才是要跑的程式)

guang@petlab-SZ77:~$ sudo docker run -t -i base/archlinux:latest bash
[root@43933e26eb35 /]#

Commit Image

每次運行container時,都是重新載入image。所以如果沒有commit,下一次運行又會是嶄新的一頁

先touch file

[root@4f2fd20777a8 /]# touch HELLO-DOCKER!
[root@4f2fd20777a8 /]# ls
HELLO-DOCKER!  bin  boot  dev  etc  home  lib  lib64  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

查看目前運行的container

sudo docker ps -a

CONTAINER ID        IMAGE                   COMMAND             CREATED             STATUS              PORTS               NAMES
4f2fd20777a8        base/archlinux:latest   bash                29 seconds ago      Up 29 seconds                           thirsty_torvalds

commit image

sudo docker commit -m "First commit!" 4f2fd20777a8 my_arch

這樣子就會把state存下來了

sudo docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
my_arch             latest              40ad47b774e1        44 seconds ago      282.9 MB
base/archlinux      2014.07.03          ea234cde99e6        5 months ago        282.9 MB
base/archlinux      2014.04.01          56c61f5c2920        5 months ago        293.3 MB
base/archlinux      latest              dce0559daa1b        5 months ago        282.9 MB

可以看到多了一個剛剛commit的image

下一次就可以直接使用已經my_arch的這個images囉

guang@petlab-SZ77:~$ sudo docker run -t -i my_arch bash
[root@b267cc485624 /]# ls
HELLO-DOCKER!  bin  boot  dev  etc  home  lib  lib64  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

Check container details

sudo docker inspect [container ID]

透過inspect可以看continer的狀態,比如說container的IP

Stop container

sudo docker stop [container ID]

若是要將container移除,一定要先stop

stop後也可用sudo docker start [container ID]重新執行

Remove container

sudo docker rm [container ID]

一次移除所有container
sudo docker ps -a -q | xargs sudo docker rm

Remove Image

sudo docker rmi [Image ID]

Reference

https://docs.docker.com/installation/ubuntulinux/#ubuntu-trusty-1404-lts-64-bit
https://docs.docker.com/articles/basics/
http://philipzheng.gitbooks.io/docker_practice/content/appendix_command/README.html

 
about 4 years ago

Pipe是由程式自己建立的”管道“

管道有兩端,一邊唯讀一邊唯寫

in —> [[安安我是管道]] —> out

這在shell中會時常用到
cat file1 | less
把 cat file1的stdout導到less的stdin,利用pipe當作中間的橋梁

這邊要記錄一下如何在C對pipe進行操作

[建立管道]
透過pipe()這個system call來建立

//[0] : read from pipe ,[1] : write to pipe
int pipe_fd[2];
//建立pipe,失敗回傳-1
pipe(pipe_fd);

[操作管道]
把操作pipe的方式想成跟stdin/stdout一樣就可以了

write(pipe_fd[1],Hello,5);//write to pipe
char buff[5];
read(pipe_fd[0],buff,5);//read from pipe

[關閉管道]
管道沒用一定要關掉,遵守有new就要free的原則,否則可能會產生deadlock

close(pipe_fd[0]); //close read end
close(pipe_fd[1]); //close write end

通常搭配fork來使用,使得process之間可以互相溝通

Reference:
http://www.gnu.org/software/libc/manual/html_node/Creating-a-Pipe.html
https://www.ptt.cc/bbs/b97902HW/M.1268932130.A.0CF.html