Sometime you might want to create a flash drive (USB drive) for installing Windows, but... on Linux. One of the simple way is to use UNetbootin. However, the recent versions of UNetbootin do not support NTFS partition anymore, and you just cannot create such a drive in usual way.
Fortunately, UNetbootin is not support NTFS partition in GUI only, it still work like a charm with the command line options.
Now, it is time to begin.
0. I assume that you have a ISO file of Windows 7 (or 8) Installation Disk (win7.iso, for example) and a flash drive with the capacity of at least 4GB (which is recognized as /dev/sdd, for example.) I also assume that you already have UNetbootin in your system.
1. First of all, creating a partition which is big enough for storing Windows installation packages. It should be larger than 3.2 GB. You can use any tool that you are familiar with, such as gparted, Disk Utility, etc. I use parted here for example.
$ sudo parted -s /dev/sdd mklabel msdos mkpart primary 1024KiB 4GiB print
$ sudo mkfs.ntfs -L WIN /dev/sdd1
2. Mount the created partition to a point in your system. If you use Genome, it should mount that partition automatically to /run/media/${USER}/WIN. If it is not the case, use the following command.
$ sudo mount /dev/sdd1 /mnt
3. Run the following command.
$ sudo unetbootin method=diskimage isofile=win7.iso targetdrive=/dev/sdd1
The GUI will be shown with all the options you need. Click OK.
Blah, blah, blah...
Showing posts with label Linux. Show all posts
Showing posts with label Linux. Show all posts
Thursday, March 6, 2014
Saturday, August 11, 2012
SOCKS Proxy over SSH with OpenSSH (Linux) or PuTTY (Windows)
Do you want to use a proxy for surfing Internet without using untrusted proxies? If you have a SSH account to a server with an Internet connection, this article will show you how to create your own SOCKS proxy for above purpose. I will also show you how to do that on both Linux and Windows.
A more advantage command which I normally use is as follow.
Please check the man page of ssh for options.
Open PuTTY an declare information such as host name as normal.
The important part is to open a port for listening locally as a SOCKS proxy. Change to "Tunnels" category; fill the port to "Source port" and choose "Dynamic"; click on "Add" button.
Now, you can back to the "Session" category and click on "Open" button to log in to your server.
To avoid session timeout, you should tell PuTTY to send some null packets to the server after some duration. To do that, go to "Connection" category and fill out the number of seconds between null packet sending.
That is enough for proxy. You now have a SOCKS proxy listening on port 1080. It is time to configure web browser redirect every connection via newly created proxy.
Declare the proxy information as in the following screenshot.
Click on OK and OK again. That's all! You now can access to an IP check service to confirm that your web connection routed via the proxy. You can try IP2LOCATION.
Change to "Connections" tab and click on "LAN settings" button.
On the "Local Area Network (LAN) Settings" dialog, un-check "Automatically detect settings" and check on "Use a proxy server for your LAN (These settings will not apply to dial-up or VPN connections)." Then click on "Advanced" button.
Declare information as in the above screenshot and click on OK.
On Google Chrome, you can open the system proxy settings by choosing "Settings -> Show advanced settings... -> Change proxy settings..."
Hope this article is useful to you, sometime ;).
1. Create SOCKS Proxy
Linux
On Linux, all you need is an OpenSSH client which is normally installed by default by almost distros. Open Terminal and run the following command to create a SOCKS proxy which listens for connections on port 1080.$ ssh -D 1080 username@hostname
A more advantage command which I normally use is as follow.
$ ssh -NCf -o "ServerAliveInterval 300" -D 1080 username@hostname
Please check the man page of ssh for options.
Windows
PuTTY might be the most popular SSH client on Windows. Fortunately, it also supports SOCKS proxy. You should use the latest version which can be downloaded from here.Open PuTTY an declare information such as host name as normal.
![]() |
| The main window of PuTTY where you can declare host name, port, etc. |
Now, you can back to the "Session" category and click on "Open" button to log in to your server.
To avoid session timeout, you should tell PuTTY to send some null packets to the server after some duration. To do that, go to "Connection" category and fill out the number of seconds between null packet sending.
That is enough for proxy. You now have a SOCKS proxy listening on port 1080. It is time to configure web browser redirect every connection via newly created proxy.
2. Web Browser Configuration
Firefox
If you use Firefox, you can set the proxy information by accessing "Options" dialog on Windows or "Preferences" dialog on Linux. Then change to "Advanced" category; choose "Network" tab and click con the "Settings..." button.Declare the proxy information as in the following screenshot.
Click on OK and OK again. That's all! You now can access to an IP check service to confirm that your web connection routed via the proxy. You can try IP2LOCATION.
Chrome and Internet Explorer
Both Google Chrome and Internet Explorer use the system settings for the proxy. You can declare the information by opening "Internet Options" dialog from Control Panel or Internet Explorer or Chrome.Change to "Connections" tab and click on "LAN settings" button.
On the "Local Area Network (LAN) Settings" dialog, un-check "Automatically detect settings" and check on "Use a proxy server for your LAN (These settings will not apply to dial-up or VPN connections)." Then click on "Advanced" button.
Declare information as in the above screenshot and click on OK.
On Google Chrome, you can open the system proxy settings by choosing "Settings -> Show advanced settings... -> Change proxy settings..."
Hope this article is useful to you, sometime ;).
Tuesday, July 31, 2012
Cache Issues in the I/O Performance Test
Tags:
benchmark,
cache,
I/O,
Linux,
performance
Sometime you have to benchmark IO performance such as file read/write. If it was the first time you did such kind of task, you almost probability notice that the reading speed is very high, hundreds of MB per second, with a slow hard disk, such as mechanical one with 5400rpm. That is the effects of file caching.
I will show you here some techniques to overcome or minimize the cache effects.
The easiest way is to umount and re-mount the corresponding mount point. For example,
On Linux, you can clear or drop cache of the OS by using the following command.
The former part of the above command will commit buffer cache to disk, and the latter part will tell OS to drop buffer caches immediately.
There are three levels of dropping cache with corresponding numbers.
1 - Free pagecache
2 - Free dentries and inodes.
3 - Free pagecache, dentries, and inodes.
When you open a file with the flag O_DIRECT, you bypass the I/O buffers and therefore bypass the cache effects of cache at the operating system level. Almost device drivers support POSIX compatible API also support O_DIRECT flag, except of some parallel distributed file systems such as PanFS.
Benchmark tools such as IOR (-B), IOzone (-I), dd (direct) have flag for this feature. In programming, use the following example.
If you want to clear cache for a specific file, you can use the following program clearcache.c to tell OS not to cache the file. It actually helps you clear cache of a list of files provided via program's arguments.
The most important part in the above code is posix_fadvise(), which tells OS that the specified data will not be accessed in the near future.
I will show you here some techniques to overcome or minimize the cache effects.
1. Re-mount
The easiest way is to umount and re-mount the corresponding mount point. For example,
# umount /home # mount /home
2. Clear Cache of the OS
On Linux, you can clear or drop cache of the OS by using the following command.
# sync && echo 3 > /proc/sys/vm/drop_caches
The former part of the above command will commit buffer cache to disk, and the latter part will tell OS to drop buffer caches immediately.
There are three levels of dropping cache with corresponding numbers.
1 - Free pagecache
2 - Free dentries and inodes.
3 - Free pagecache, dentries, and inodes.
3. Use Direct I/O for POSIX
When you open a file with the flag O_DIRECT, you bypass the I/O buffers and therefore bypass the cache effects of cache at the operating system level. Almost device drivers support POSIX compatible API also support O_DIRECT flag, except of some parallel distributed file systems such as PanFS.
Benchmark tools such as IOR (-B), IOzone (-I), dd (direct) have flag for this feature. In programming, use the following example.
open(filename, O_DIRECT);
4. Clear Cache for a Specific File
If you want to clear cache for a specific file, you can use the following program clearcache.c to tell OS not to cache the file. It actually helps you clear cache of a list of files provided via program's arguments.
/* clearcache.c - mrcuongnv */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
int
clear_file_cache(filename)
char *filename;
{
int fd, rs;
printf("%s", filename);
if ((fd = open(filename, O_RDONLY)) != -1) {
if ((rs = posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED)) == 0) {
printf(" --> Cleared\n");
return 0;
}
}
printf(" --> %s (%d)\n", strerror(errno), errno);
return 1;
}
int
main(argc, argv)
int argc;
char *argv[];
{
if (argc < 2) {
fprintf(stderr, "Syntax: %s FILES\n", argv[0]);
return 1;
}
int i, rs = 0;
for (i = 1; i < argc; i++) {
rs += clear_file_cache(argv[i]);
}
return rs;
}
The most important part in the above code is posix_fadvise(), which tells OS that the specified data will not be accessed in the near future.
Tuesday, April 3, 2012
Decode .HQX File on Linux
A very simple solution is to use UUDeview which is available in many Linux distros. You can also use macutils on Debian-based distros. Or even easier, an online tool is here.
On Fedora:
On Debian/Ubuntu:
To decode file fxppd1110bm922ien.hqx, for example, you can use the following command.
Have a good day!
On Fedora:
# yum install uudeview
On Debian/Ubuntu:
# apt-get install uudeview
To decode file fxppd1110bm922ien.hqx, for example, you can use the following command.
$ uudeview -i fxppd1110bm922ien.hqx
Have a good day!
Thursday, November 24, 2011
How to Change MAC Address on RHEL/CentOS/Fedora
On the RHEL/CentOS/Fedora boxes, there is a line named HWADDR in the interface configuration file /etc/sysconfig/network-scripts/ifcfg-eth0, for example, storing the MAC address of the corresponding ethernet interface.
Nothing will happen if you change the MAC addresss in this line, and you will probably receive the following notice when restart the network service.
Shutting down interface eth0: Device eth0 has MAC address AA:BB:CC:DD:EE:FF, instead of configured address 00:11:22:33:44:55. Ignoring.
To change the MAC address, just keep the HWADDR as it is, and add the following line to the above file.
MACADDR=00:11:22:33:44:55
Restart the network service.
# service network restart # ifconfig eth0
New MAC address! Congrats!!!
Note: You should change eth0 to eth1, or the Ethernet interface you want to change its MAC address.
Sunday, August 30, 2009
Sử dụng Nginx và memcached để tăng tốc Apache trên Debian Lenny
Tác giả: Nguyễn Việt Cường (a.k.a. mrcuongnv)
Trong bài viết này, tôi giới thiệu cách thức cài đặt Nginx kết hợp với memcached trên Debian "lenny" 5.0 nhằm tăng hiệu năng phục vụ của web server mà ở đây là Apache 2.2. Bài viết này là tổng hợp từ nhiều nguồn khác nhau trên Internet và là bản ghi chép của tôi trong quá trình nâng cấp một web server thực tế có lượng truy cập lớn.
1. Giới thiệu
Gần đây, web server mà tôi quản lí (phi vụ lợi) có lượng truy cập tăng đột biến mà không phải vì bị tấn công. Tải (load) của server những lúc cao điểm thường lên ~40 trong khi chỉ có 8 cores phục vụ với 8GB RAM. Công việc tối ưu bắt đầu.
Chúng tôi chỉ có một server duy nhất nên web server, db server được đặt chung với nhau. Điều này là một bất lợi lớn. Nhưng không sao, chúng ta phải chấp nhận vì có một server tốt như thế để hoạt động phi vụ lợi là rất tốt rồi.
Ban đầu, tôi tưởng rằng vấn đề nằm ở DB server (MySQL) vì theo dõi thấy có rất nhiều lệnh thực hiện rất lâu, đặc biệt là các lệnh thực hiện phép nối bảng lớn. Chúng tôi đã tiến hành tối ưu MySQL rồi đặt cron để tối ưu toàn bộ CSDL 2 ngày một lần. Vấn đề có vẻ như được giải quyết khi server chạy liên tục 2 tháng liền mà không gặp bất cứ trục trặc gì. Tuy nhiên, gần đây thì tình trạng tải tăng cao lại tiếp tục diễn ra, đặc biệt là quãng 20-24h (giờ Việt Nam). Tôi đã xem xét lại chi tiết và phát hiện ra rằng, những lúc tải tăng cao thì DB server không hoạt động mấy, rất ít câu lệnh được thực hiện (lúc tải < 20). Tuy nhiên khi tải ~30-40 thì một số câu lệnh SQL đột nhiên thực hiện rất lâu, điều này có thể giải thích là các tiến trình của web server đã chiếm hết tài nguyên rồi thì làm sao db server chạy nhanh được nữa. Như vậy thì ta phải tối ưu web server thôi.
Sau một hồi hỏi anh Google và chị Bing, tôi quyết định sẽ sử dụng Nginx để làm proxy ngược (reverse proxy) cho Apache và kết hợp sử dụng memcached để lưu những dữ liệu tĩnh (static file) vào trong bộ nhớ.
Theo định nghĩa trên Wikipedia thì:
- Nginx (phát âm giống "engine x") là một máy chủ web (web server), proxy ngược (reserve proxy) và e-mail proxy (IMAP/POP3) nhẹ, hiệu năng cao, sử dụng giấy phép kiểu BSD. Nó có thể chạy trên UNIX, Linux, các dòng BSD, Mac OS X, Solaris và Microsoft Windows.
- memcached (phát âm là mem-cash-dee) là một hệ thống lưu trữ bản sao các đối tượng (objects) và dữ liệu được truy cập nhiều lần để tăng tốc độc truy xuất. Nó thường được sử dụng để tối ưu hóa việc tải dữ liệu từ cơ sở dữ liệu cho các ứng dụng trên nền web. Vào lúc đầu, hệ thống memcached được phát triển bởi Danga Interactive và dùng cho LiveJournal. Sau đó memcached trở nên phổ biến và được dùng trên các trang web khác.
Vì sao tôi không sử dụng thẳng Nginx để làm web server? Lí do ở đây là vì Apache tỏ ra tốt hơn Nginx trong việc phục vụ các trang web động (dynamic page) (điều này tôi tham khảo trên web, sẽ kiểm tra trong một bài khác). Một trong những nguyên nhân là do Nginx sử dụng FastCGI, mà cái này thì chậm. Vậy là mô hình đã hình thành: Apache sẽ chạy ở dưới, phục vụ trên một cổng khác (8080); còn Nginx chạy ở trên, phục vụ trên cổng (80). Các request tới web server sẽ đi qua Nginx trước, rồi sau đó sẽ được chuyển qua Apache để xử lí và trả kết quả ngược lại cho Nginx; tiếp đó Nginx sẽ trả về cho client. Tuy nhiên nếu request đó không phải là một trang web động mà lại là một nội dung tĩnh thì hành động này có vẻ như thừa thãi. Giải pháp đưa ra là (1) Nginx sẽ phục vụ trực tiếp các file tĩnh hoặc (2) Nginx sử dụng memcached để ghi nhớ các file đó trong bộ nhớ và chỉ việc lấy ra khi cần thiết.
Trên server của tôi có chứa nhiều website (shared server) và để chống hack local thì chúng tôi sử dụng ACL kết hợp mpm-itk để tăng cường bảo mật. Khi sử dụng mpm-itk thì mỗi website sẽ được chạy dưới một uid và gid riêng. Điều này không tương thích với Nginx vì nó chỉ chạy được với một uid và gid duy nhất., do vậy không có đủ quyền để truy cập trực tiếp vào thư mục của các website Do vậy chúng tôi phải sử dụng giải pháp memcached để giúp Nginx có thể phục vụ trực tiếp client với các file tĩnh.
Các bạn cũng nên lưu ý là khi cài đặt memcached rồi thì có rất nhiều phần mềm mã nguồn mở sử dụng được cái này để tăng hiệu năng như Drupal, vBulletin, phpBB,... và không kể hết...
2. Cài đặt
Trong bài viết này, tôi chỉ hướng dẫn cài đặt trên Debian "lenny" 5.0. Cài đặt trên Ubuntu "chắc" cũng tương tự, nếu có thì chỉ là thay đổi chút ít. Ở đây tôi không hướng dẫn cài ACL và mpm-itk mà sẽ giới thiệu trong một dịp khác.
Trước hết, chúng ta phải cài đặt Apache, PHP, Nginx và memcached.
# aptitude install apache2 libapache2-mod-php5 libapache2-mod-rpaf nginx memcached
Chúng ta cần cài module rpaf của Apache vì request gửi đến Apache sẽ xuất pháp từ Nginx và do vậy mang IP của máy chạy Nginx. Module rpaf sẽ giúp Apache nhận ra IP thực của client trong request mà Nginx gửi sang.
Bây giờ chúng ta sẽ phải sửa file cấu hình của apache2 để cho nó chạy trên cổng 8080. Mở file /etc/apache2/ports.conf, thay 80 bằng 8080 ở hai dòng sau:
NameVirtualHost *:80 Listen 80
Ta được:
NameVirtualHost *:8080 Listen 8080
Bật module php5 và rpaf:
# a2enmod php5 rpaf
Ta tạo một website làm ví dụ, ở đây tôi sử dụng tên miền blog.cuongnv.com. Ta tạo một file cấu hình cho website này như sau:
# vi /etc/apache2/sites-available/blog.cuongnv.com
Và điền nội dung như sau (thư mục gốc cho web của domain này là /home/www/blog.cuongnv.com/public_html).
<VirtualHost *:8080> ServerName blog.cuongnv.com ServerAdmin blog@cuongnv.com DocumentRoot "/home/www/blog.cuongnv.com/public_html" <Directory "/home/www/blog.cuongnv.com/public_html"> Options -Indexes FollowSymLinks MultiViews AllowOverride All </Directory> ErrorLog /var/log/apache2/blog.cuongnv.com_error_log LogFormat "%h %l %>s %b" common CustomLog /var/log/apache2/blog.cuongnv.com_access_log common </VirtualHost>
Kích hoạt domain này (bản chất là tạo một soft link trong thư mục /etc/apache2/sites-enabled tới file tương ứng trong thư mục /etc/apache2/sites-available):
# a2ensite blog.cuongnv.com
Khởi động lại dịch vụ Apache:
# /etc/init.d/apache2 restart
Khởi động lại dịch vụ memcached nếu chưa tự khởi động khi cài xong:
# /etc/init.d/memcached restart
Như vậy là xong phần cấu hình cho Apache. Bây giờ chúng ta sẽ cấu hình cho Nginx. Cấu trúc thư mục trong /etc của Nginx cũng hoàn toàn tương tự như của Apache.
Trước hết, ta tạo file cấu hình cho module proxy của Nginx. Các thông tin này lấy từ web site của Nginx.
# vi /etc/nginx/proxy.conf
Điền nội dung sau:
proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffer_size 4k; proxy_buffers 32 4k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k;
Bây giờ là công việc cấu hình một virtual host cho domain blog.cuongnv.com để tương ứng với Apache. Tạo file:
# vi /etc/nginx/sites-avaiable/blog.cuongnv.com
Với nội dung như sau:
server {
listen 80;
server_name blog.cuongnv.com;
access_log /var/log/nginx/blog.cuongnv.com.access.log;
location / {
proxy_pass http://blog.cuongnv.com:8080;
include /etc/nginx/proxy.conf;
}
location ~ \.php$ {
proxy_pass http://blog.cuongnv.com:8080;
include /etc/nginx/proxy.conf;
}
# Danh sach file tinh vi dụ
location ~* ^.+.(jpg|jpeg|gif|png|ico|css|tar|mid|midi|wav|js)$ {
expires max;
set $memcached_key "$scheme://$host$request_uri";
memcached_pass 127.0.0.1:11211;
error_page 404 = /fallback;
}
location /fallback {
internal;
expires max;
proxy_pass http://blog.cuongnv.com:8080;
include /etc/nginx/proxy.conf;
break;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/nginx-default;
}
}
Kích hoạt domain trên:
# ln -s /etc/nginx/sites-available/blog.cuongnv.com /etc/nginx/sites-enabled/
Khởi động lại Nginx:
# /etc/init.d/nginx restart
Bây giờ bạn đã có thể truy cập vào website vừa cấu hình một cách bình thường do Nginx phục vụ, ở đây là: http://blog.cuongnv.com. Ngoài ra, bạn có thể truy cập trực tiếp dịch vụ của Apache tại http://blog.cuongnv.com:8080. Tất nhiên đây là các link giả định, thực tế phải là đường link của bạn.
Trong file cấu hình ở trên, chúng ta đã cấu hình để những yêu cầu tới file có đuôi là .php sẽ được chuyển cho Apache phục vụ. Các file tĩnh (với đuôi được liệt kê ở trước đó) thì được tìm kiếm trong memcached, nếu memcached không có thì sẽ chuyển cho Apache phục vụ (lỗi 404 chuyển qua /fallback). Việc tìm kiếm này sử dụng key là URL đầy đủ của file tương ứng, bao gồm scheme (http, https), host (blog.cuongnv.com), uri đầy đủ (uri và query string).
Tuy nhiên, cần phải đặc biệt chú ý, Nginx không hề giúp ta cache các file vào trong memcached một cách tự động mà ta phải tự tay làm việc đó. Trong hệ thống của tôi thì tôi sử dụng một script để cache tất cả các file tĩnh cần thiết vào trong bộ nhớ. Việc này được thực hiện định kì một lần mỗi ngày.
Script này tôi tham khảo từ blog của Levent Serinol viết bằng PHP. Hiện tại tôi đang viết một script khác có thể duyệt qua tất cả các virtual host hiện tại và cache cho toàn bộ các host đó với các file có đuôi và độ lớn nhỏ hơn một ngưỡng cho trước. Tôi sẽ public script này trong một vài ngày tới.
Cài đặt php5-cli để chạy được các file php trên dòng lệnh:
# aptitude install php5-cli
Tạo file tương ứng trong /etc/cron.daily:
# vi /etc/cron.daily/cache_static_file.php
Điền nội dung sau:
#!/usr/bin/php5
<?php
function rscandir($base = '', &$data = array())
{
$array = array_diff(scandir($base), array('.', '..'));
foreach ($array as $value)
{
if (is_dir($base.$value))
{
$data = rscandir($base . $value . '/', $data);
}
elseif (is_file($base.$value))
{
$rest = substr($value, -4);
if ((!strcmp($rest,'.jpg')) ||
(!strcmp($rest,'.png')) ||
(!strcmp(substr($value, -3),'.js')) ||
(!strcmp($rest,'.css')) ||
(!strcmp($rest,'.gif')) )
{
$data[] = $base.$value;
}
}
}
return $data;
}
$mylist=rscandir("/home/www/blog.cuongnv.com/public_html");
$srch = array('/home/www/blog.cuongnv.com/public_html');
$newval = array('http://blog.cuongnv.com');
$memcache_obj = memcache_connect('127.0.0.1', 11211);
while (list($key, $val) = each($mylist))
{
$url = str_replace($srch, $newval, $val);
echo "$key => $url -> " . filesize($val) . "\n";
$value = file_get_contents($val);
memcache_add($memcache_obj, $url, $value, false, 0);
}
?>
Sửa quyền của file để là file chạy và khởi động lại dịch vụ cron:
# chmod a+rx /etc/cron.daily/cache_static_file.php # /etc/init.d/cron restart
Tài liệu tham khảo
Chúc các bạn thành công!
- Nginx wiki
- Top 10 Nginx Tutorial
- Using Nginx As Reverse-Proxy Server On High-Loaded Sites
- Speeding up your nginx server with memcached
Chúc các bạn thành công!
Tuesday, August 25, 2009
Chuyển hướng xuất/nhập trong Linux
Tags:
Linux,
Pipeline,
Standard IO
Tác giả: Nguyễn Việt Cường (a.k.a. mrcuongnv), OSG ColTech
Bài viết này được mình viết dành tặng riêng cho các thành viên của Diễn đàn FOTECH.ORG. Bài viết được đăng đầu tiên tại đây. Trong bài này, mình cập nhật lại các ví dụ vì trang web chính thức của nhóm OSG đã được chuyển từ địa chỉ http://osg.vnu.edu.vn sang http://osg.vnuh.org.
Hôm nay nhân chuyện có người hỏi về làm thế nào để chạy một lệnh một cách "âm thầm" tức là không in cái gì ra màn hình cả, mình viết một cái tut nhỏ về chuyện này. Ví dụ đưa ra ở đây là lệnh curl, chi tiết về cú pháp lệnh thì sử dụng man curl trên Linux hoặc trên Google.
Trước hết, ta sẽ đi thẳng vào vấn đề rồi sau đó mới giải thích. Để một lệnh chạy trong chế độ "âm thầm" như vậy thì ta thêm đoạn sau vào đuôi lệnh:
> /dev/null 2>&1
Mà cụ thể nếu ta muốn làm công việc đó với lệnh curl thì như sau:
$ curl http://osg.vnuh.org/ > /dev/null 2>&1
Vì sao lại làm thế? Dấu > có ý nghĩa gì? /dev/null là cái gì mà ghê gớm thế? 2>&1 là cái gì mà trông kì lạ thế? Đó cũng là những thắc mắc của mình khi bước vào thế giới Linux/Unix.
1. Giới thiệu
Trên hầu hết các hệ điều hành nói chung và Linux/Unix nói riêng thì có 3 dòng xuất nhập chuẩn (I/O) là STDIN, STDOUT và STDERR mà chức năng tương ứng là dòng nhập chuẩn, dòng xuất chuẩn và dòng xuất lỗi chuẩn. Chúng được gọi là các open file và hệ thống gán cho mỗi file này một con số gọi là file descriptor. Ba con số tương ứng với 3 dòng xuất nhập chuẩn ở trên là 0, 1 và 2. Cụ thể:
standard input → stdin → 0<
standard output → stdout → 1>
standard error → stderr → 2>
Trong C++ thì 3 dòng xuất nhập chuẩn này tương ứng với 3 đối tượng cin, cout và cerr.
Chú ý: Trong bài tut này thì mình sử dụng Bourne shell trong đó dấu $ thể hiện user bình thường và # thể hiện user root. Tuy nhiên hầu hết nội dung trong bài này có thể áp dụng với một số loại shell khác như sh, csh, tcsh... Với C chell (csh, tcsh) thì không sử dụng được các con số (file descriptor).
2. Xuất/Nhập
Trong chế độ command line của hầu hết các hệ điều hành thì < dùng cho chuyển hướng nhập và > dùng cho chuyển hướng xuất. Vì sao phải chuyển hướng? Vì có nhiều lúc ta muốn kết quả xuất ra màn hình được lưu lại vào một file và dữ liệu nhập vào thay vì từ bàn phím thì lại từ một file.
2.1. STDIN
STDIN chỉ các dòng nhập chuẩn nói chung và nó thường là từ bàn phím. Khi chúng ta gõ bàn phím tức là chúng ta đang nhập vào STDIN. Để dữ liệu đầu vào là một file thì ta dùng dấu <. Ví dụ, nếu ta dùng lệnh cat mà không có tham số thì khi ta gõ gì nó sẽ hiển thị ra cái đó, hay nói đúng hơn sẽ hiển thị lại những gì ta nhập vào từ input chuẩn. Vậy thì giả dụ ta cần hiển thị file /etc/passwd thì ngoài cách truyền thống là
$ cat /etc/passwd
thì ta có thể sử dụng:
$ cat < /etc/passwd
hoặc
$ cat 0< /etc/passwd
Tại sao lại có thể bỏ số 0 mà chức năng vẫn tương tự? Đó là vì mỗi khi khởi tạo một process thì hệ thống đã gắn một dòng nhập chuẩn cho process đó mà ở đây là STDIN hay 0.
2.2. STDOUT
STDOUT là các dòng xuất chuẩn nói chung và nó thường là xuất ra màn hình, ra cửa sổ console hoặc terminal. Để dữ liệu đầu ra được ghi vào một file thì ta sử dụng dấu >. Ví dụ ta muốn danh sách các file trong một thư mục được ghi vào file dir.txt thì ta sử dụng lệnh sau:
$ ls -al > dir.txt
hoặc
$ ls -al 1> dir.txt
Lí do vì sao có thể bỏ số 1 đi tương tự như với STDIN, tức là khi khởi tạo một process thì hệ thống đã gắn một dòng xuất chuẩn cho process đó mà ở đây là STDOUT hay 1.
Đến đây ta có thể kết hợp sử dụng song song STDIN và STDOUT để làm thao tác copy file. Ví dụ ta muốn backup file /etc/passwd thì ta có thể làm như sau:
$ cat < /etc/passwd > ~/passwd.bak
Lệnh này tương đương với lệnh:
$ cp /etc/passwd ~/passwd.bak
Có một ứng dụng cực kì có ích của việc kết hợp này là chuyển đổi file text giữa Windows và Unix. Như các bạn đều biết thì trong file text của Windows, việc xuống dòng được thể hiện bằng cặp kí tự \r\n còn trong Linux/Unix thì chỉ là \n. Ai phải code trên cả hai môi trường đều thấy sự bất tiện của việc chuyển đổi đó. Giải pháp đưa ra ở đây là sử dụng lệnh tr, cụ thể như sau:
$ tr -d '\r' < win.cpp > unix.cpp
Lệnh này sẽ nhận dòng nhập chuẩn sau đó xoá các kí tự \r rồi ghi ra dòng xuất chuẩn. Dòng nhập và dòng xuất ở đây được định hướng lại để đến từ một file và ghi ra một file.
Tuy nhiên nếu dùng > thì nội dung của file sẽ bị xoá trước khi ghi nội dung mới. Nếu ta muốn nội dung mới sẽ được ghi nối tiếp vào file thì ta sử dụng 2 dấu lớn hơn, tức là >>. Ví dụ nếu bạn muốn nối nội dung của thư mục /home vào cuối file passwd.bak ở trên thì bạn làm như sau:
$ ls /home >> ~/passwd.bak
Bây giờ nếu ta muốn lấy mã HTML của trang chủ của OSG và ghi vào file osg.html thì ta sử dụng lệnh sau:
$ curl http://osg.vnuh.org/ > osg.html
Thực hiện lệnh trên các bạn có thấy gì lạ không? Mặc dù mã HTML thay vì xuất ra màn hình mà được đưa vào file osg.html nhưng vẫn có các thông tin thể hiện trạng thái download hiển thị trên màn hình. Làm thế nào mà lại được như thế? Làm thế nào để lệnh curl câm lặng hoàn toàn? Hồi sau sẽ rõ.
2.3. STDERR
STDERR là dòng xuất lỗi chuẩn nói chung và nó cũng thường xuất trực tiếp ra màn hình, console hay terminal. Cú pháp tương tự như STDOUT, tức là sử dụng > để xuất ra file và >> để nối vào một file đã có (chưa có thì hệ thống sẽ tự tạo ra). Tuy nhiên điểm khác biệt là bạn phải chỉ rõ số 2, tức là 2> hoặc 2>>. Lí do là vì chỉ có 1 dòng xuất chuẩn và 1 dòng nhập chuẩn cho mỗi process mà thông thường hệ thống chỉ định là STDOUT và STDIN.
Vậy trong trường hợp của lệnh curl trong phần 2.2 ở trên, nếu ta muốn ghi cả 2 loại output đó ra file thì ta làm như sau:
$ curl http://osg.vnuh.org/ > osg.html 2> osg.log
Thế nào? Không có cái gì xuất ra màn hình hết đúng không? Vì nội dung trang web đã được lưu vào file osg.html còn các dòng lưu trạng thái download đã được ghi vào file osg.log.
Nhưng thế thì tốn dung lượng đĩa và có nguy cơ gây hỏng đĩa vì phải ghi file mà. Con người quả thật quá tham lam. Vậy thì phải sáng tạo ra cái gì đó như kiểu cái thùng không đáy hay gọi mĩ miều hơn thì nó là "lỗ đen" hay "black hole", tức là một nơi mà cho cái gì vào cũng mất hút luôn. Linux/Unix có cái đó cho bạn, đó là /dev/null.
2.4. /dev/null
In Unix-like operating systems, /dev/null or the null device is a special file that discards all data written to it (but reports that the write operation succeeded), and provides no data to any process that reads from it (it returns EOF). In Unix programmer jargon, it may also be called the bit bucket or black hole.
Tạm dịch là:
Trong các hệ điều hành kiểu Unix, /dev/null hay thiết bị null là một tệp tin đặc biệt, nó bỏ qua mọi dữ liệu ghi lên nó (nhưng có báo cáo về việc ghi dữ liệu thành công) và không cung cấp bất kì dữ liệu gì khi đọc từ nó (trả về EOF). Trong biệt ngữ của các lập trình viên Unix, nó đuợc gọi là "bit bucket" hoặc "black hole".
Vậy thì đó chính là cái ta cần rồi. Như vậy câu lệnh curl ở trên có thể cho nó thực hiện câm lặng bằng cách:
$ curl http://osg.vnuh.org/ > /dev/null 2> /dev/null
Không có cái gì xuất ra màn hình cả, cũng không có cái gì được ghi lại cả. Nhưng... lại nhưng, con người vẫn tham lắm, làm thế nào để cái lệnh trên ngắn gọn hơn, trông technical hơn, nói chung là để ai không biết thì sẽ không hiểu gì (đôi khi đó là cái thú của dân kĩ thuật). Ta sẽ dùng 2>&1 ở đây, tức là:
$ curl http://osg.vnuh.org/ > /dev/null 2>&1
Câu lệnh trên tức là dòng xuất chuẩn (1) sẽ bị đưa vào /dev/null và dòng lỗi chuẩn (2) sẽ được đưa vào dòng xuất chuẩn (1) mà ở đây là /dev/null.
Đặc biệt lưu ý là với cú pháp sử dụng dấy & thì dấu & và dấu > phải đi liền nhau, không có khoảng cách.
Ngoài các file descriptor 0, 1, 2 ở trên thì còn có từ 3 → 9 nữa. Tuy nhiên bài viết này chỉ dành cho mức độ newbie nên không để cập sâu, chi tiết các bạn có thể tự tìm hiểu thêm trên Internet hoặc trong các sách về lập trình shell.
3. Pipe
Như vậy chúng ta đã biết cách để chuyển hướng dòng xuất/nhập của một lệnh hay một process. Bằng cách này ta có thể chuyển dữ liệu xuất của một lệnh thành dữ liệu nhập của một lệnh khác thông qua một file trung gian. Tuy nhiên ta không muốn có file trung gian đó, một phần vì việc ghi lên đĩa cứng, phần khác là do... tham. Đó chính là vấn đề mà pipe giải quyết. Trong Linux, ta sử dụng dấu | để làm việc này.
Ví dụ khi ta muốn xem lại nội dung thư mục /etc nhưng kết quả của nó lại dài quá mà ta muốn xem lại thì ta làm như sau
$ ls -al /etc | more
hoặc
$ ls -al /etc | less
(thoát bằng phím q).
hoặc ta muốn đếm số user trong hệ thống có sử dụng mặc định bash shell thì ta làm như sau:
$ cat /etc/passwd | grep "/bin/bash" | wc -l
Lệnh này có nghĩa là đưa nội dung file /etc/passwd ra dòng xuất chuẩn; dòng xuất chuẩn này thành dòng nhập chuẩn của lệnh grep và lệnh này chỉ lọc ra các dòng có chưa xâu /bin/bash để đưa ra dòng xuất chuẩn; dòng xuất chuẩn này lại thành dòng nhập chuẩn của lệnh wc -l là lệnh đếm số dòng của dòng nhập chuẩn và đưa ra số dòng ra dòng xuất chuẩn; cuối cùng dòng xuất chuẩn này sẽ được đưa ra trực tiếp màn hình vì nó không thành dòng nhập chuẩn của lệnh nào nữa.
4. Tài liệu tham khảo
Subscribe to:
Posts (Atom)







