Posted on

線上練習Linux指令

有的時候我們可能需要練習Linux指令,但是又沒有一台Linux的主機
方法之一就是起一台虛擬機器,但是如果單純指是想要測試簡單的指令的話,線上有許多方便好用的工具可以供我們直接操作

JSLinux

網站連結:JSLinux
網站截圖

Copy.sh

網站連結:copy.sh
網站截圖:

Webminal

網站連結:webminal
網站截圖:

Linux Containers

網站連結:Linux Containers
網站截圖:

Posted on

使用Plink快速在Linux伺服器下指令

軟體介紹

下載連結:Download
Plink是Putty工具裡面的一個小工具,多被使用在自動執行的部份
若我們可能在自動化部署檔案到伺服器的前後自動執行某些SSH的指令,可以使用PLink來做到這個需求。
Plink可以將連進server並執行某指令用一行指令便做到。

指令介紹


使用介紹

  • 自動連上(包含 username 與 passwd)
    c:\plink -ssh login.example.com -l(空格)名字 -pw(空格)密碼
  • 在遠端機器上, 批次執行一堆指令
    c:\plink -ssh login.example.com -l(空格)名字 -pw(空格)密碼 命令1;命令2

    ex:
    c:\plink -ssh login.example.com -l(空格)名字 -pw(空格)密碼 ls;echo Hello World;ls

參考資料

Posted on

Linux 基本操作指令介紹

檔案操作相關

  • pwd: 顯示目前目錄
  • cd: 更換目錄
  • ls: 顯示檔案名稱與內容的指令(-a可顯示隱藏檔,-al同時顯示隱藏檔與詳細資料 )
  • cat: 將檔案內容列出的指令
  • more: 檔案太大的話,可以用 more 來一頁頁讀取喔(如: ls -al|more)
  • mkdir: 建立新的目錄
  • rm: 刪除的指令,如rm test.txt,如果要刪掉整個資料夾下的檔案,則可以加-irf,如rm -rf test
  • rmdir: 刪除資料夾的指令,但如果資料夾內有內容則需要使用rm -rf
  • mv: 移動檔案或目錄
  • cp: copy 的意思
  • find:尋找檔案的指令
  • whereis:相對於 find ,你也可以使用 whereis 這個指令來下達找尋的檔案,whereis 利用曾經找過的系統資訊內的資料去找檔案,所以速度會很快,不過,如果 whereis 找不到的話,並不代表該檔案真的不存在
  • chmod:變更檔案屬性的指令
  • chown:變檔案有擁有者
  • chgrp:改變檔案或目錄的『擁有群組』
  • df:察看硬碟空間的指令
  • du:用來察看目錄內所有檔案使用掉的空間的情況
  • ifconfig: 用來查詢目前我們這個系統的網路卡的狀況的指令,可以查詢 IP、子遮罩網路及網路卡的硬體資訊等等。
  • adduser username:新增使用者
Posted on

Linux 設定開機自動執行程式

所有使用者登入自動執行指令

執行以下指令
vi /etc/profile

在裡面打入要執行的指令如下:
/home/gtwang/my_script.sh

然後記得要有執行權限
chmod +x /home/gtwang/my_script.sh

個別使用者登入自動執行指令

如果只是要讓個別使用者登入執行的程式,就寫在使用者個人的 ~/.bash_profile、~/.bash_login 或是 ~/.profile 當中,就看自己的家目錄下所使用的是那一個,就把指令加進去即可,bash 在使用者登入時,會依序尋找這三個檔案,它只會執行第一個找到的那一個,假設 ~/.bash_profile 這個檔案存在,它就會執行這一個,而後面兩個就不管了,以此類推。

依據不同執行類型修改不同設定檔

另外,/etc/bash.bashrc ~/.bashrc 也是很常被使用的 bash 設定檔,這兩個檔案的用途跟上面的 profile 設定檔很類似,不過有些差異:

  • profile 設定檔:登入型 shell(login shell)所執行的指令稿,例如使用者登入。
  • bashrc 設定檔:非登入型 shell 所執行的指令稿,例如開啟終端機視窗。

登出自動執行指令

若要設定使用者登出時所要自動執行的程式,可將指令寫在自己的 ~/.bash_logout 指令稿中(如果不存在,就自己建立一個),例如:
/home/gtwang/my_script2.sh
同樣要確認執行權限:
chmod +x /home/gtwang/my_script2.sh

Posted on

VI文書處理器

Linux的文書處理器

若要使用Linux來管理伺服器,文書處理是很重要的,因此會需要了解如何操作Linux裡的文書編輯軟體VI。
要呼叫VI的方式如下

VI的三種使用模式

因為純鍵盤的操作,又需要可以支持打字,因此VI將操作模式分為下面三種

  • 一般模式:可以使用『上下左右』按鍵來移動游標,您可以使用『刪除字元』或『刪除整行』來處理檔案內容,也可以使用『複製、貼上』來處理您的文件資料
  • 編輯模式: 用來編輯檔案內容,按下『i, I, o, O, a, A, r, R』其中一個可以進入編輯模式,畫面的左下方會出現『 INSERT 或 REPLACE 』的字樣。
  • 指令列命令模式:輸入『 : 或 / 』就可以將游標移動到最底下那一行。可做儲存搜尋等動作


左下方的I代表現在正在編輯模式

一般模式

  • [Ctrl] + [f]: 螢幕『向前』移動一頁
  • [Ctrl] + [b]: 螢幕『向後』移動一頁
  • /word: 向游標之後尋找一個字串名稱為 word 的字串。
  • ?word: 向游標之前尋找一個字串名稱為 word 的字串。
  • :n1,n2s/word1/word2/g : 在第 n1 與 n2 行之間尋找 word1 這個字串,並將該字串取代為 word2 !
  • :1,$s/word1/word2/g : 從第一行到最後一行尋找 word1 字串,並將該字串取代為 word2 !
  • :1,$s/word1/word2/gc: 從第一行到最後一行尋找 word1 字串,並將該字串取代為 word2 !且在取代前顯示提示字元給使用者確認(conform)是否需要取代!
  • x 為向後刪除一個字元, X 為向前刪除一個字元
  • dd刪除游標所在的那一整列
  • yy:複製游標所在的那一行,20yy 則是複製 20 列
  • p 為複製的資料在游標下一行貼上,P 則為貼在游標上一行!
  • u: 復原前一個動作。

編輯模式

  • i, I插入:在目前的游標所在處插入輸入之文字,已存在的文字會向後退;
  • a, A增加:由目前游標所在的下一個字開始輸入,已存在的文字會向後退:
  • o, O插入新的一行:從游標所在的下一行枝行首開始輸入文字
  • r, R取代:r 會取代游標所在的那一個字元;R會一直取代游標所在的文字,直到按下 ESC 為止;
  • Esc退出編輯模式,回到一般模式中

指令列命令模式

  • :w 將編輯的資料寫入硬碟檔案中
  • :q 離開 vi
  • :wq 儲存後離開,若為 :wq! 則為強制儲存後離開
  • :e! 將檔案還原到最原始的狀態!
  • ZZ 若檔案沒有更動,則不儲存離開,若檔案已經經過更動,則儲存後離開!
  • :w [filename] 將編輯的資料儲存成另一個檔案(類似另存新檔)
  • :r [filename] 在編輯的資料中,讀入另一個檔案的資料。亦即將 『filename』 這個檔案內容加到游標所在行後面
  • :set nu 顯示行號,設定之後,會在每一行的字首顯示該行的行號
  • :set nonu 與 set nu 相反,為取消行號!
  • n1,n2 w [filename] 將 n1 到 n2 的內容儲存成 filename 這個檔案。
  • :! command 暫時離開 vi 到指令列模式下執行 command 的顯示結果!例如[ :! ls /home ]

後面加上!則代表強制執行

Posted on

Linux用pm2來管理伺服器

pm2介紹

pm2 是一個管理 Node.js process 的工具,它可以讓我們用簡單的指令啟動 Node.js cluster 並最大化使用我們的 CPU,可以利用它來簡化很多node應用管理的繁瑣任務,如性能監控、自動重啟、負載均衡等,而且使用非常簡單。

安裝

使用npm安裝
npm install pm2 -g

目錄介紹

pm2安裝好後,會自動創建下面目錄。
$HOME/.pm2 將包含所有PM2相關文件
$HOME/.pm2/logs 將包含所有應用程序日誌
$HOME/.pm2/pids 將包含所有應用程序pids
$HOME/.pm2/pm2.log PM2記錄
$HOME/.pm2/pm2.pid PM2 pid
$HOME/.pm2/rpc.sock 遠程命令的套接字文件
$HOME/.pm2/pub.sock 可發布事件的套接字文件
$HOME/.pm2/conf.js PM2配置

啟動程序

pm2 start後面加上node.js 起始檔案
pm2 start app.js
使用叢集(cluster)的方式來起始檔案
pm2 start -i 4 –name server app.js

刪除Process

根據id, name刪除process
pm2 delete { id or name }

停止Process

根據id, name停止process
pm2 stop { id or name }

重新啟動Process

根據id, name重新啟動process
pm2 restart { id or name }

監控

列出目前所有已啟動的process並顯示他們目前的狀態, 按下ctrl+c 可以離開monitor
pm2 monit

利用叢集增加效能

請參考此篇文章:使用 pm2 啟動 Node.js cluster 以提升效能
截取作者實測結果報告:

可以發現開多個 process 處理的時候,消化 1000 個 request 的時間從 17.4 秒降到 9.9 秒,而每個 request 的回應時間也從 1668ms 降到 930ms,整體的速度大概快了兩倍(我的電腦是四核心,如果配備更好的話會快更多)

參考資料

Posted on

在Linux與Windows間傳送檔案

PSCP介紹

PSCP 是一套使用命令提示列的軟體,是PuTTY相關可選擇使用的軟體。它提供 SCP client 的功能。當我們僅需要將一個或少數檔案從 pc 端 upload 到 server 端時,這套軟體就提供非常安全的方法,使得所傳送的內容不會被其他人給竊聽。倘若遠端有提供 SSH2 建議還是使用 PSFTP 會比較好。

檔案下載:pscp.exe
下載原站:Download PuTTY: latest release (0.72)

linux傳送檔案到windows

下載單一檔案: /claire/test.txt為linux檔案位置,/tmp為windows要下載到的位置

pscp claire@8.8.8.8:/claire/test.txt /tmp

下載整個資料夾: /claire/為linux檔案位置,/tmp為windows要下載到的位置

pscp -r claire@8.8.8.8:/claire /tmp

windows傳送檔案到linux

pscp c:\123.xls root@xxx.xxx.xxx.xxx:/home/uploads

代表將於Windows之C槽下的一123.xls檔案,
傳送至IP為xxx.xxx.xxx.xxx的Linux中的/home/uploads資料夾下。

參考資料

Posted on

PieTTY : 免費的SSH及Telnet client

軟體介紹

軟體下載:pietty0400b14.exe
官方網站:PieTTY:A terminal forked from PuTTY by piaip

PuTTY 是個小巧方便的 Telnet/SSH 安全遠端連線程式, 但用於非英語系文字時有非常多的問題, 而且它對於初學者來說過於複雜的使用界面也為人詬病已久。 PieTTY (舊稱 pputty) 則是源自於 PuTTY ,修正與完整支援亞洲等多國語系字元、 並在使用界面上大幅改進、易學易用的版本。

連線至Linux伺服器


按下『連線』後,就會出現等待登入與輸入帳/密資料的畫面,輸入帳密後就可以連線到遠端的linux電腦了。

如果想更改程式的編碼,可以選擇『選項 > 字元編碼 > 想顯示的編碼』,這樣就可以正常顯示各種不同編碼的文字

更多的連線方式

如果想要嘗試更多的連線方式,可以至此文章有更詳盡的介紹:
鳥哥的 Linux 私房菜 第十一章、遠端連線伺服器SSH / XDMCP / VNC / RDP

參考資料

Posted on Leave a comment

單元測試 – 重構測試

重構test的重要性

好的測試應該要容易維護,容易閱讀,
不應包含程式邏輯在內,因此像是if, while, for迴圈等都不應該出現在測試裡
如果我們驗證的內容會和資料有關,則建議使用Substitute,這樣可以讓我們能夠在每一個測試裡增加不同的資料
而且可以直接在每個測試裡看到資料的內容是什麼
下面是一個範例
private void AmountShouldBe(int expected, DateTime start, DateTime end)
{
IList data = new List()
{
new Budget() {Amount = 310, YearMonth = “201801”},
new Budget() {Amount = 620, YearMonth = “201803”},
new Budget() {Amount = 900, YearMonth = “201804”}
};

var budgetCalculator = new BudgetCalculator(new TestDataBudgetRepository(data));
var budget = budgetCalculator.TotalAmount(start, end);
Assert.AreEqual(expected, budget);
}
91的課程中建議每一次寫成功一個測試案例,就可以先做重構,這樣之後的的開發速度可以更加速

重構測試的步驟

  • 抽出field: mock object(繼承假物件去創建假物件), stub(用Substitute)
  • Setup: SUT初始化(或者[TestInitialize])
  • 抽出方法(用Given為開頭):定義mock object行為,代表假如在跑這個scenario時…
  • Extra Method with “Shouldxxx()” => SUT行為+Assertion

也就是盡可能讓我們的重構能夠符合3A原則,
3A pattern: Arrange, Act, Assert
上面重構後Arrange就用Given…,然後Act就是SUT行為,Assert就是Assertion。

重構的測試的範例

下面為重構後的程式碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NSubstitute;
using NUnit.Framework;
using RsaSecureToken;
using Assert = NUnit.Framework.Assert;

namespace RsaSecureToken.Tests
{
[TestFixture]
public class AuthenticationServiceTests
{
private IProfile _fakeProfile;
private IRsaToken _fakeToken;
private ILogger _logger;
private AuthenticationService _authenticationService;

[SetUp]
public void Given()
{
_fakeProfile = Substitute.For();

_fakeToken = Substitute.For();

_logger = Substitute.For();

_authenticationService = new AuthenticationService(_fakeProfile, _fakeToken, _logger);
}

private void GivenToken(string token)
{
_fakeToken.GetRandom(“”).ReturnsForAnyArgs(token);
}

private void GivenPassword(string account, string password)
{
_fakeProfile.GetPassword(account).Returns(password);
}

private void ShouldBeValid(string account, string password)
{
var actual = _authenticationService.IsValid(account, password, _logger);
Assert.IsTrue(actual);
}

[Test()]
public void IsValidTest()
{
GivenPassword(account: “joey”, password: “91”);
GivenToken(token: “000000”);

ShouldBeValid(account: “joey”, password: “91000000”);
}

[Test()]
public void IsInValidTest()
{
GivenPassword(account: “joey”, password: “91”);
GivenToken(token: “000000”);

ShouldBeInValid(account: “joey”, errorPassword: “error password”);
}

private void ShouldBeInValid(string account, string errorPassword)
{
var actual = _authenticationService.IsValid(account, errorPassword, _logger);
Assert.IsFalse(actual);
}

[Test()]
public void ShouldLog()
{
GivenPassword(account: “joey”, password: “91”);
GivenToken(token: “000000”);

ShouldBeInValid(account: “joey”, errorPassword: “error password”);

//這個可能會有過度指定的問題,或許加一個痘號就會導致測試失敗
//_logger.Received(1).Save(Arg.Is(“account: joey try to login failed”));
_logger.Received(1).Save(Arg.Is(m => m.Contains(“joey”) && m.Contains(“login failed”)));
}
}
}