Thực thi dưới dạng .test chứ không phải ./test


26

Giả sử tôi đang ở trong cùng thư mục với một tệp thực thi, tôi sẽ cần phải nhập tệp này để thực thi nó:

./file

Tôi thà không phải gõ /, vì /tôi khó gõ.

Có cách nào dễ dàng hơn để thực hiện một tập tin? Lý tưởng nhất chỉ là một số cú pháp đơn giản như:

.file

hoặc một cái gì đó khác nhưng dễ dàng hơn là phải chèn /nhân vật ở đó.

Có lẽ có một số cách để đặt một cái gì đó vào /binthư mục hoặc tạo bí danh cho trình thông dịch, để tôi có thể sử dụng:

p file

9
Có thể trao đổi / với một khóa khác bằng xmodmap? Vì vậy, ít nhất nó dễ dàng hơn để gõ
Guy

26
Là một lưu ý phụ, /được sử dụng rộng rãi trong Unix, phần lớn là một trình phân tách thư mục. Bạn có lẽ tốt hơn là tìm một cách dễ dàng hơn để gõ nó.
chrylis -on đình công-

7
@RossPresser Câu hỏi này rất ít ý nghĩa kể từ đó. và ./ ở đầu tập tin là hai ý nghĩa hoàn toàn khác nhau vì lý do kỹ thuật mà bất kỳ người mới bắt đầu nào cũng nên biết. /không khó để đánh máy cho đại đa số mọi người và nếu OP gặp chấn thương ngăn chặn điều này, họ nên xem xét bố trí bàn phím thay thế, vì không có cách nào họ có thể tránh /hoàn toàn khi ở trong thiết bị đầu cuối.
JFA

1
@JFA Phần lớn các bố trí bàn phím được sử dụng ở lục địa châu Âu cũng như Nam Mỹ đã /sử dụng shift-7, tương đối khó gõ, thậm chí không có chấn thương.
nitro2k01

6
Chỉnh sửa lịch sử: " tại sao không thể chỉ dẫn Giao diện mạng được thực hiện đơn giản để thực hiện tất cả các truy vấn internet thông qua máy chủ từ xa qua ssh trên cổng 22. " _ಠ
Derek 會 8/2/2017

Câu trả lời:


35

Nó có thể là "rủi ro" nhưng bạn có thể có. trong ĐƯỜNG của bạn.

Như đã nói ở những người khác, điều này có thể nguy hiểm vì vậy luôn luôn đảm bảo. là ở phần cuối của ĐƯỜNG chứ không phải là bắt đầu.


1
Đừng thực sự thấy điều đó "rủi ro" như thế nào: con đường của tôi đã diễn ra như vậy từ rất lâu trước linux và nó chưa bao giờ gây ra vấn đề nhỏ nhất.
jamesqf

21
@jamesqf Thật rủi ro vì nếu bạn cdvào một thư mục có thể ghi được trên thế giới và cố gắng sử dụng một lệnh không có trong đường dẫn của bạn, bạn có thể thực thi một lệnh (có thể là độc hại) có thể được thực thi bằng cùng tên mà ai đó đã viết cho đường dẫn đó. Điều này tồi tệ hơn nhiều nếu bạn đặt .ở đầu con đường của bạn. Trong trường hợp đó, một lệnh thực thi độc hại được gọi lssẽ được thực thi nếu bạn cố gắng gọi lstrong thư mục đó.
byte hóa vào

2
Hãy tránh điều này, vì những lý do được chỉ định ở trên. Các plệnh sẽ tốt hơn.
Guido

11
@jamesqf Khi đó là hệ thống "của bạn" và chỉ có bạn sử dụng nó, nó không quá tệ. Vấn đề xuất hiện (và đã vấp phải nhiều quản trị viên Unix trong nhiều năm qua) trên hệ thống nhiều người dùng. Với một .sớm trong PATH, tất cả một độc hại nhu cầu người sử dụng phải làm là thả một giả lslệnh trong thư mục của họ và thuyết phục các admin để "nhìn vào một cái gì đó kỳ lạ" và họ đã có quyền truy cập root.
TripeHound

1
Giải pháp tốt, mặc dù nó sẽ không hoạt động nếu tệp tình cờ được đặt tên test, như trong tiêu đề của câu hỏi (vì testlà một vỏ được tích hợp sẵn và có lẽ cũng tồn tại ở đâu đó trong bạn $PATH).
yellowantphil

71

.sẽ tự động hoàn thành./ (gõ .và nhấn Tab) ít nhất trong các vỏ Bash hiện đại, vì vậy bạn không cần phải sử dụng PATHgiải pháp phức tạp hoặc không an toàn (như sửa đổi).

Nếu nó không tự động hoàn tất, bạn có thể cần phải cài đặt gói "bash-hoàn thành".


Bạn có chắc không? .có nhiều ứng cử viên hoàn thành: .(thư mục hiện tại), ..(thư mục gốc), .lệnh (bash cung cấp bí danh không chuẩn sourcecho) và bất kỳ dấu chấm nào hiện diện. Có lẽ bash-completiongói bỏ qua điều này; Tôi thấy điều đó thật khó chịu (ví dụ, nó khiến cho các tên thư mục hoàn thành trong một makedòng lệnh không thể thực hiện được và nói chung là khủng khiếp với các tệp thực hiện có đầy đủ các quy tắc ngầm) vì vậy tôi luôn luôn lọc nó.
R ..

3
Tôi đã thử nó, và vâng, nó tự động hoàn thành theo cách này. Trong hầu hết mọi trường hợp, đó là điều mà một người dùng thông thường mong muốn: Tôi không nghĩ rằng tôi đã từng thấy một dotfile có thể thực thi được, chạy một cái gì đó trong thư mục con là phổ biến hơn nhiều so với chạy một cái gì đó trong thư mục mẹ và IMO nó một công việc tốt chết tiệt của việc tìm kiếm makemục tiêu.
l0b0

Với bash 3.2, nó không tự động hoàn tất. Điều này có thể là mới trong bash 4?
Calimo

2
@Calimo Nhiều khả năng mới trong các phiên bản gần đây của bash-hoàn thành. Đó là một sự thay đổi cơ bản.
l0b0

42

hoặc .. có lẽ cung cấp cho trình thông dịch một bí danh trong tệp bashrc và sau đó chỉ đơn giản là

   p  file

Có thể viết một hàm như vậy:

p() {
 ./"$@"
}

trong của bạn ~/.bashrc. Sau đó, bạn sẽ có thể chạy p app argumentsthay vì ./app arguments. Giải pháp này hoạt động cho các tệp thực thi thuộc bất kỳ loại nào, bao gồm các tập lệnh và tệp nhị phân.

"$@"mở rộng để liệt kê một cách thích hợp danh sách các đối số được truyền cho hàm (bảo toàn tất cả các ký tự đặc biệt khỏi mở rộng toàn cầu hoặc biến), và, như @Scott chỉ ra, bashđủ thông minh để trả trước ./cho một trong số chúng, bảo toàn phần còn lại.


Mặc dù việc chạy ứng dụng theo lệnh khác ít phổ biến hơn, như strace -f p appđể xem các cuộc gọi hệ thống được thực hiện hoặc $(which time) p appđể xem mất bao lâu. pnhư một kịch bản thực thi sẽ hoạt động tốt hơn trong hai ví dụ cụ thể mà tôi đã đưa ra. Không giải pháp nào có thể làm việc với ldd p app, mặc dù ldd cũng khác nhau trong việc yêu cầu một đường dẫn đầy đủ, có lẽ vì những lý do như thế này.
sourcejedi

Có, thay thế p app argsbằng ./app argsmột cách vô hình với bất kỳ ai sẽ yêu cầu đầu vào vỏ ống thông qua một số loại tiền xử lý và sẽ gây ra tất cả các loại niềm vui khi sự thay thế xảy ra ở một nơi ngoài ý muốn :)
aitap

1
Trong trường hợp này, không nên có dấu ngoặc kép xung quanh $@? Nếu không, nó sẽ chỉ truyền một đối số lớn cho chương trình.
Kroltan

7
@Kroltan số $@là một mảng. Khi được mở rộng bên trong ", mỗi tham số sẽ mở rộng thành một từ riêng biệt. $*cư xử theo cách bạn đang nghĩ
8bittree

3
Tôi tin rằng bạn đã làm điều này phức tạp không cần thiết, và đó p() { ./"$@"; }là tất cả những gì bạn cần.
Scott

11

Bạn có thể đặt .vào của bạn $PATHbằng cách thêm ví dụ PATH=$PATH:.vào /etc/profile, theo cách này bạn có thể thực hiện filechỉ bằng cách viết file, trừ khi nó nằm trong một thư mục khác trong đường dẫn của bạn (ví dụ /usr/bin/). Lưu ý rằng điều này thường không phải là một ý tưởng tốt.

Tại sao nó xấu: Giả sử bạn đang ở trong một tình huống mà bạn không hoàn toàn tin tưởng vào nội dung của một thư mục - bạn đã tải nó từ một nơi nào đó tinh ranh và bạn muốn điều tra nó trước khi chạy nó, hoặc bạn là một sysadmin giúp đỡ một số người dùng bằng cách tìm trong thư mục chính của họ, v.v. Bạn muốn liệt kê thư mục, vì vậy bạn cố gắng gõ ls, nhưng rất tiếc, bạn tạo một lỗi đánh máy và cuối cùng thay vào đó là gõ sl. Tác giả của thư mục độc hại này đã lường trước điều này và đặt một tập lệnh shell vào nó có tên là "sl" chạy 'rm -rf --no-reserved-root /' (hoặc một cái gì đó độc hại hơn như cài đặt rootkit).

(Cảm ơn @Muzer đã giải thích)


13
Mặc dù tôi hoàn toàn đồng ý, nhưng có lẽ nó sẽ giải thích chính xác lý do tại sao đây không phải là một ý tưởng tốt.
ymbirtt

16
Tại sao nó xấu: Giả sử bạn đang ở trong một tình huống mà bạn không hoàn toàn tin tưởng vào nội dung của một thư mục - bạn đã tải nó từ một nơi nào đó tinh ranh và bạn muốn điều tra nó trước khi chạy nó, hoặc bạn là một sysadmin giúp đỡ một số người dùng bằng cách tìm trong thư mục chính của họ, v.v. Tác giả của thư mục độc hại này đã lường trước điều này và đặt một tập lệnh shell vào nó có tên là "sl" chạy 'rm -rf --no-reserved-root /' (hoặc một cái gì đó độc hại hơn như cài đặt rootkit).
Muzer

2
Đáng để giải thích rằng nếu thư mục hiện tại ở đầu $ PATH, kẻ tấn công chỉ có thể ghi đè ls hoặc các lệnh phổ biến khác
Délisson Junio

@Muzer Huuuge giấy thiếc mũ đây.
Gà Sombrero

4
@GillBates Đó là điều bạn cần cảnh giác với tư cách là một sysadmin, người phải đối phó với những người dùng thực sự và có khả năng độc hại, hoặc một người phân tích tài liệu lưu trữ đáng ngờ để kiếm sống. Nếu không ai trong số đó áp dụng, thì tôi đồng ý với bạn. Mặc dù vậy, tôi vẫn không nghĩ rằng đó là một thói quen tốt để tham gia, bởi vì bạn không bao giờ biết khi nào hoàn cảnh của bạn sẽ thay đổi, bạn có một trong những công việc này và bạn sẽ tự nguyền rủa bản thân vì đã rèn luyện bản thân để dựa vào hành vi không an toàn; )
Muzer

10

Bạn có thể gọi thông dịch viên, ví dụ

bash test

Trong trường hợp này, tập lệnh sẽ chạy ngay cả khi nó không có dòng shebang (ví dụ #!/bin/bash) cũng như bit thực thi. Bạn sẽ phải biết trình thông dịch chính xác để chạy nó. Bạn có thể đọc dòng shebang của tệp trước để đảm bảo bạn gọi đúng trình thông dịch, ví dụ nếu dòng shebang nói

#!/usr/bin/env python3

bạn sẽ gọi

python3 test

7
thông dịch viên chỉ diễn giải mã, họ sẽ không chạy các tệp nhị phân
Mc Kernel

Câu trả lời này có phần hợp lý vì có lẽ trình thông dịch có thể được cung cấp một bí danh trong tệp bashrc.

5
@McKernel điểm tốt, nó chỉ hoạt động nếu có một trình thông dịch, không dành cho các tệp thực thi được biên dịch
Zanna

2
có một thông dịch viên cho các thực thi được biên dịch:/lib/ld.so
Dmitry Kudriavtsev

7

Theo tôi biết, không có cách nào để đạt được nó trừ khi bạn bao gồm tệp trong đường dẫn env, vì vậy bạn có thể chạy nó chỉ bằng cách gõ: file

.filesẽ không hoạt động vì đó là một tên tập tin khác. Nó là một tập tin được gọi .filevà không ./file.

Tôi cảm thấy rằng dấu gạch chéo có thể khó gõ cho bạn vì bố cục không phải tiếng Anh, có thể? Trong trường hợp đó, điều đó cũng xảy ra với tôi, vì vậy tôi thường xuyên trao đổi bố cục bàn phím của mình sang tiếng Anh bằng cách nhấn Alt + Shift trong Windows (Tôi sử dụng Linux từ ssh)


7

Mọi người đã đề nghị thêm .vào PATH, điều này rất nguy hiểm vì nó tạo ra rủi ro rằng bạn sẽ vô tình chạy một chương trình độc hại được trồng trong một thư mục có thể ghi trên thế giới. Nhưng, nếu bạn có các chương trình thực thi trong một vài thư mục mà bạn sở hữu và chỉ có thể ghi được bởi bạn, thì có an toàn (khá an toàn không?) Để đưa các giám đốc đó vào PATH, bằng cách thêm một dòng như

PATH=$PATH:~/dev/myprog1:~/dev/myprog2

vào ~/.bashrctập tin của bạn . Tất nhiên điều này có nghĩa là bạn có thể chạy một chương trình từ một trong những thư mục đó từ bất kỳ đâu trong hệ thống tập tin. Ví dụ, bạn có thể cd /etcvà gõ foo, và nó sẽ chạy ~/dev/myprog1/foo. Điều này có một nhược điểm nhỏ là bạn không thể có các chương trình cùng tên trong nhiều hơn một trong các thư mục. Cụ thể, nếu bạn có các chương trình được gọi foo trong cả hai ~/dev/myprog1~/dev/myprog2, bạn sẽ không thể chạy chương trình thứ hai trừ khi chỉ định đường dẫn. Tương tự như vậy nếu bạn có một ~/dev/myprog1/cat- nhưng tại sao bạn muốn?


Một cách tiếp cận khác, nếu bạn chỉ có một vài chương trình mà bạn thực hiện điều này, là xác định bí danh cho chúng:

alias gizmo='./gizmo'
alias gonzo='./gonzo'

Hoặc bạn có thể gọi các bí danh .gizmo.gonzo nếu bạn thấy điều đó trực quan hơn.

Trên thực tế, điều này, ở một mức độ nào đó, rủi ro bảo mật tương tự như đưa .vào của bạn PATH. Nếu một người dùng độc hại có thể đọc .bashrcvà xem bí danh của bạn, thì anh ta có thể đặt phần mềm độc hại được gọi gizmogonzotrong các thư mục ngẫu nhiên với hy vọng rằng bạn sẽ chạy nó. Tốt hơn là làm cho chúng sử dụng tên đường dẫn tuyệt đối:

alias gizmo='~/dev/myprog1/gizmo'
alias gonzo='~/dev/myprog2/gonzo'

Nhân tiện, bạn nên tránh đặt tên một tệp thực thi test, bởi vì đó là lệnh dựng sẵn shell và bạn chỉ có thể chạy một chương trình theo tên đó bằng cách chỉ định một đường dẫn hoặc một số mẹo khác.


Ngoài ra, bạn có thể tạo một công thức (nếu bạn sử dụng Makefiles) và làm make gizmohoặc make gonzo.
ihato

Tôi xin lỗi, nhưng tôi không chắc là tôi hiểu nó liên quan đến câu hỏi hay câu trả lời của tôi như thế nào. Bạn có gợi ý rằng OP tạo một thư mục Makefiletrong mỗi thư mục, sao cho các hành động make gizmokết thúc bằng cách chạy gizmo ? (1) Đó có vẻ là một cách khó xử khi thực hiện điều tương tự như pchức năng, được đề xuất trong câu hỏi, ban đầu được thực hiện bởi aitap và được Scott tinh chỉnh. (2) Bạn có thể vượt qua các đối số theo cách đó? ISTM make gizmo arg1 arg2tương đương với make gizmo; make arg1; make arg2.
G-Man nói 'Phục hồi Monica'

1
(1) Có lẽ giả định của tôi là sai nhưng đối với tôi OP không muốn sử dụng eschew ./trong mọi thư mục . Trong tâm trí của tôi, anh ấy đang phát triển một cái gì đó và chỉ cần chạy chương trình được sản xuất ./filethường xuyên. Tôi thực sự không thể nghĩ đến bất kỳ kịch bản nào khác mà người ta thường xuyên cần chạy một tệp cục bộ và nếu anh ta không chạy nó thường xuyên, anh ta không bận tâm đặt câu hỏi (anh ta nói khó không phải không thể ) (2) không thực sự nhưng bạn có thể vượt qua các đối số trong công thức.
ihato

(1) Chà, tôi đoán chúng ta có thể đồng ý rằng động lực của OP và phạm vi câu hỏi của anh ấy không rõ ràng. (2) Cảm ơn liên kết.
G-Man nói 'Phục hồi Monica'

3

Để mở rộng câu trả lời của Zanna về trình thông dịch (xin lỗi, không có đại diện cho nhận xét): "trình thông dịch" cho các tệp thực thi gốc (còn gọi là tệp ELF nhị phân) là trình tải động ( ld.so), nhưng nó thường không hiểu cú pháp bạn muốn:

$ /usr/lib/ld-linux-x86-64.so.2 program
program: error while loading shared libraries: program: cannot open shared object file
$ /usr/lib/ld-linux-x86-64.so.2 ./program
<program is launched>

(ngoài ra, trừ khi bạn symlink ld.sovào đường dẫn của mình, bạn vẫn cần phải viết /s)


Đây là đặc thù của Linux, phải không? Bạn có thể vui lòng giải thích điều này nhiều hơn, tại sao điều này làm việc? Tôi nghĩ rằng hạt nhân (Linux) sẽ thực hiện phân tích cú pháp và quyết định xem có nên chạy nhị phân hay không, đó binfmt_misclà để làm gì .
phk

2
@phk Tệp này dành riêng cho Linux, nhưng khái niệm về trình liên kết / trình tải động thì không. Chẳng hạn, FreeBSD có cái rất riêng /libexec/ld-elf.so.1. Trên Linux, nó không đơn giản như "quyết định cách chạy nhị phân": binfmt_miscphát hiện định dạng của tệp bằng các số ma thuật (ELF, tập lệnh shebang, CIL). Sau đó, binfmt_elfxử lý được gọi. Nó phân tích các tiêu đề và phần ELF; .interpphần chứa đường dẫn của bộ tải động; trình tải này được khởi động bởi kernel, thực hiện chuyển vị trí và nhảy tới _start. Trên FreeBSD (không chắc chắn về người khác) không có binfmt, nhưng nguyên tắc là +/- tương tự.
bacondropping

1
@phk về lý do tại sao điều này hoạt động - ld.sokhông có .interpvà được liên kết tĩnh, điều đó có nghĩa là nó không cần một trình liên kết / trình tải động khác để giải quyết các ký hiệu bên ngoài của nó và thực hiện phép toán di dời.
bacondropping

ISTR Solaris cũng có một cái gì đó tương đương với điều này.
G-Man nói 'Phục hồi Monica'

3

Nếu chúng ta được phép bắt đầu cấu hình mọi thứ

mkdir -p ~/.local/bin
cat > ~/.local/bin/x << 'EOF'
#!/bin/sh
N="$1"
shift
exec "./$N" "$@"
EOF
chmod a+x ~/.local/bin/x

Hầu hết các phân phối hiện đại bao gồm ~ / .local / bin trong $ PATH đã có (thêm export PATH="$HOME/.local/bin:$PATH"vào ~/.profilenếu bạn không có). Sau đó, bạn có thể sử dụng x fileđể chạy ./file.

Đừng cố gắng xác định một .lệnh. Lệnh . scriptđã chạy scripttrong shell hiện tại. Điều này cho phép scriptxác định các biến môi trường cho shell hiện tại.


3
Tôi nghĩ rằng có thể có một gợi ý tốt ở đây, nhưng không có lời giải thích nào về những điều này. Tôi có thể giải quyết nó, nhưng một người dùng thiếu kinh nghiệm sẽ không có cơ hội.
IMSoP

Không cần phải thay đổi $ 1. Chỉ cần exec "$@".
Revierpost

$ (ln -s /bin/ls my-ls && exec my-ls) # bash: exec: my-ls: not found
sourcejedi

(1) Không cần thiết phải shift $1; chỉ exec ./"$@". (2) Vì bạn đang nói về một tập lệnh shell, nên sẽ hơi vô nghĩa / sai lệch khi khuyên mọi người không nên xác định .lệnh, vì không thể tạo tệp được gọi .. (Có thể, và rất khó có thể xác định hàm bí danh hoặc hàm được gọi ..)
Scott

1

Nếu chúng tôi được phép tạo tập lệnh của trình trợ giúp, bạn có thể tạo một trình trợ giúp thêm pwd vào PATH, sau đó chạy

. pathhelper    #adds pwd to path
file            #now it can be run without ./

Điều này tránh thêm "." đến đường dẫn và gây ô nhiễm .profile của bạn với mọi đường dẫn mà bạn có thể muốn chạy một cái gì đó vào một lúc nào đó.

Chúng ta có thể thực hiện phương pháp này một bước xa hơn bằng cách tạo ra một người trợ giúp khởi chạy một lớp vỏ mới với một PATH được sửa đổi. Nếu nó lấy một thư mục làm tham số (sử dụng pwd làm mặc định), nó sẽ hoạt động như một pushdchỉnh sửa đường dẫn. Bạn có thể phải lưu ý rằng mọi thay đổi đối với các biến môi trường khác sẽ bị mất khi thoát khỏi lớp con, nhưng trong một lớp vỏ dài, biến PATH của bạn sẽ không bị lộn xộn. Tùy thuộc vào quy trình công việc của bạn, điều này có thể là lợi thế.

:outer shell prompt$; subshellpathhelper    # launches a subshell with modified PATH
: subshell prompt $ ; file                  # in the subshell it can be run without ./

Nhưng tôi đoán nếu bạn muốn chạy với nó, bạn có thể hack pushdpopdvì vậy họ có thể thực hiện các sửa đổi tương tự cho đường dẫn mà không cần thực hiện một subshell sẽ làm mất các thay đổi khác.

pushd --path ~/some/path/    # normal pushd plus adds target to path
file                         # it can be run without ./ until you popd

(Bạn không thể làm tương tự với cdvì nó không có tương tự popd.)

Bạn cũng có thể tạo một cặp trợ giúp chuyên dụng để chỉ cần đẩy và bật các mục PATH. Những gì hoạt động tốt nhất thực sự phụ thuộc vào mô hình sử dụng của bạn.


Trên thực tế, bạn có thể làm một cái gì đó giống như vậy cd, nhưng nó còn ở ngoài đó: Tạo một tệp như thế .dircmdsvà hack cdđể làm cho các lệnh được xác định ./.dircmdskhông khả dụng ngay trước khi chuyển đổi và có sẵn ngay sau khi chuyển đổi.
ShadSterling

-1

Bạn có thể sử dụng . script.shcú pháp miễn là tập lệnh bạn muốn thực thi nằm trong thư mục hiện tại.

Bạn cũng có thể thêm tiền tố với trình thông dịch, như sh hoặc bash. thí dụ:bash script.sh


8
. script.shsẽ phá vỡ nếu tập lệnh chứa exit, có các hiệu ứng không mong muốn, ví dụ: nếu nó xác định lại PATH "tạm thời"; nó cũng chỉ hoạt động cho các tập lệnh cho trình bao hiện tại của bạn
sourcejedi

@sourcejedi Liên quan đến exitbạn có thể đặt nó vào trong ngoặc đơn, tức là một nhánh con, nhưng đúng, nó sẽ vẫn chỉ dành cho các tập lệnh trong cùng một trình bao.
phk

Câu hỏi cho biết, một tập tin thực thi. Chúng sẽ không hoạt động cho một thực thi nhị phân; chỉ cho một kịch bản. Và đoạn thứ hai của bạn trùng lặp câu trả lời của Zanna .
Scott

Chà, thật tệ, tôi chủ yếu thực thi và phát triển công cụ bash, vì vậy tôi cho rằng chúng ta đang nói về các tập lệnh bash :)
UltimateByte

Không chỉ cho một kịch bản, mà chỉ cho một kịch bản Bash.
Oskar Skog
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.