Sửa lỗi 'sudo: sorry, you must have a tty to run sudo' trong Ansible

intermediate🔧 Ansible2026-05-24| Ansible chạy trên RHEL 5/6, CentOS 5/6 hoặc các bản phân phối Fedora cũ. Cũng xảy ra trên các hệ thống Debian hoặc Ubuntu đã được tăng cường bảo mật (hardened).

Error Message

sudo: sorry, you must have a tty to run sudo
#ansible#sudo#become#tty#sudoers#leo-thang-dac-quyen

Vấn đề

Bạn đã kiểm tra kỹ các khóa SSH và quyền sudo, nhưng Ansible playbook của bạn vẫn gặp lỗi ngay lập tức. Thông báo lỗi rất rõ ràng: sudo: sorry, you must have a tty to run sudo. Đây không phải là lỗi trong mã của bạn. Đó là một rào cản bảo mật trên máy chủ từ xa đang chặn các tác vụ tự động không tương tác.

Điều này thường xảy ra khi quản lý các môi trường Red Hat cũ (RHEL 6 hoặc CentOS 6). Nó cũng xuất hiện trong các cụm máy chủ bảo mật cao, nơi chính sách cấm chạy sudo mà không có phiên làm việc terminal tương tác thực tế.

Tóm tắt: Cách khắc phục nhanh

Giải pháp đáng tin cậy nhất là vô hiệu hóa thiết lập requiretty trên máy chủ mục tiêu. Hãy đăng nhập vào máy từ xa, chạy lệnh visudo và vô hiệu hóa dòng sau:

# Defaults    requiretty

Nếu bạn không thể thay đổi chính sách bảo mật của máy chủ, hãy thử bật SSH Pipelining trong file ansible.cfg cục bộ để thay đổi cách truyền lệnh:

[ssh_connection]
pipelining = True

Nguyên nhân gốc rễ chi tiết

Nhân Linux sử dụng các terminal giả (pseudo-terminals - PTY) cho các phiên tương tác. Trước đây, các bản phân phối như RHEL 5 và 6 được cài đặt sẵn với tùy chọn Defaults requiretty trong file /etc/sudoers. Thiết lập này đảm bảo rằng sudo chỉ hoạt động nếu người dùng đang thực sự thao tác trên một terminal.

Ansible ưu tiên tốc độ. Theo mặc định, nó thực thi các module bằng cách truyền chúng qua SSH mà không cấp phát một PTY. Điều này giúp việc tự động hóa nhanh hơn nhưng lại kích hoạt kiểm tra bảo mật. Khi Ansible cố gắng thực hiện become: yes, hệ thống từ xa nhận thấy một luồng không tương tác thay vì một TTY và ngắt tiến trình ngay lập tức.

Các tiêu chuẩn bảo mật hiện đại thường coi requiretty có giá trị bảo mật thấp. Do đó, hầu hết các bản phân phối hiện đại như Ubuntu, Debian và RHEL 7+ đã loại bỏ hoàn toàn hạn chế này.

Cách khắc phục 1: Chỉnh sửa file Sudoers (Khuyên dùng)

Giải quyết vấn đề tại nguồn là cách sạch sẽ nhất. Bạn có hai cách để áp dụng thay đổi này một cách an toàn bằng công cụ visudo.

1. Vô hiệu hóa trên toàn hệ thống

Chạy lệnh sudo visudo trên máy mục tiêu. Tìm dòng requiretty và thêm ký tự # vào phía trước.

# Tìm dòng này:
Defaults    requiretty

# Đổi thành:
# Defaults    requiretty

2. Vô hiệu hóa cho người dùng Ansible

Bạn có thể muốn giữ chính sách này cho các người dùng khác trong khi miễn trừ cho tài khoản tự động hóa (ví dụ: ansible_user). Hãy thêm quy tắc cụ thể này vào cuối file:

Defaults:ansible_user !requiretty

Cách khắc phục 2: Bật SSH Pipelining

Nếu bạn đang quản lý hơn 500 máy chủ cũ, việc chỉnh sửa thủ công là không khả thi. Bật pipelining giúp giảm số lượng thao tác SSH cần thiết để chạy một module. Điều này thường bỏ qua yêu cầu TTY bằng cách thay đổi cách thức dữ liệu lệnh được gửi đến shell từ xa.

Chỉnh sửa file ansible.cfg trong thư mục gốc của dự án:

[ssh_connection]
pipelining = True

Lưu ý: Pipelining có thể tăng tốc độ thực thi thêm 30% hoặc hơn. Tuy nhiên, nếu cấu hình sudo của bạn yêu cầu mật khẩu (thay vì NOPASSWD), pipelining có thể khiến tác vụ bị treo. Luôn kiểm tra việc này trong môi trường staging trước.

Cách khắc phục 3: Bắt buộc sử dụng TTY (Giải pháp cuối cùng)

Bạn có thể đánh lừa máy chủ từ xa bằng cách bắt buộc Ansible cấp phát một terminal giả. Điều này mô phỏng một phiên làm việc của người dùng thực. Sử dụng cờ -tt trong các đối số SSH.

Trong file ansible.cfg của bạn:

[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s -tt

Tại sao đây là giải pháp cuối cùng: Việc ép buộc TTY thường làm hỏng các module cần luồng dữ liệu sạch. TTY có thể chèn các ký tự điều khiển ẩn hoặc tự động xuống dòng các kết quả đầu ra quá dài, dẫn đến lỗi phân tích cú pháp không mong muốn trong Ansible.

Xác minh: Kiểm tra kết quả

Sau khi áp dụng bản sửa lỗi, hãy chạy một lệnh ad-hoc nhanh. Việc này giúp xác nhận rằng tính năng leo thang đặc quyền hiện đã hoạt động trên toàn bộ danh sách máy chủ (inventory):

ansible all -m shell -a "whoami" --become

Nếu lệnh trả về root cho các máy chủ thay vì lỗi TTY, rào cản đã được gỡ bỏ.

Tổng kết

  • Nguyên nhân: Thiết lập requiretty cũ trong /etc/sudoers chặn các lệnh gọi sudo không tương tác.
  • Cách sửa tốt nhất: Vô hiệu hóa (comment out) Defaults requiretty bằng visudo.
  • Cách sửa hàng loạt: Bật pipelining = True trong cấu hình Ansible để tối ưu hóa kết nối.

Related Error Notes