When you su
to another user, your terminal device (like /dev/pts/4
) retains the ownership of your original user. This creates permission issues for programs like screen
that need to manage the terminal:
$ ls -l /dev/pts/4
crw--w---- 1 original_user tty 136, 4 Mar 15 10:30 /dev/pts/4
The script
command creates a new pseudo-terminal with proper permissions. When you run:
$ script /dev/null/
Three key things happen:
- A new PTY is created with the su'ed user's permissions
- All I/O is redirected to /dev/null (discarding output)
- You get a new shell session with proper terminal ownership
The magic happens because script
internally calls posix_openpt()
which:
int master_fd = posix_openpt(O_RDWR|O_NOCTTY);
grantpt(master_fd);
unlockpt(master_fd);
Other ways to solve this terminal permission issue:
# Method 1: Using sudo instead of su
$ sudo -iu target_user screen
# Method 2: Explicitly setting permissions
$ chmod g+rw $(tty)
Here's how this looks in a deployment script:
#!/bin/bash
# Switch to service account
su - service_acct -c "script /dev/null -c 'screen -dmS my_service ./long_running.sh'"
When you switch users with su
and attempt to launch screen
, you might encounter this frustrating error:
Cannot open your terminal '/dev/pts/4' - please check.
This occurs because su
doesn't properly handle terminal permissions when transitioning between users. The terminal device (/dev/pts/*) remains owned by your original user, while the new session tries to access it as the target user.
The solution of running:
script /dev/null/
works because it performs several critical functions:
- Creates a new pseudo-terminal with correct permissions
- Resets the terminal's controlling process
- Establishes proper session leadership
When you su
to another user:
original_user$ su - target_user
password:
target_user$ screen
Cannot open your terminal '/dev/pts/4' - please check.
The key issue is that the terminal device maintains its original ownership. Running script
creates a new PTY master/slave pair with correct permissions. The /dev/null
destination simply discards output rather than creating a typescript file.
For more permanent solutions, consider these approaches:
# Option 1: Use sudo instead of su
sudo -u target_user -i screen
# Option 2: Reset terminal permissions manually
chmod 666 /dev/pts/4
# Option 3: Use expect to handle the transition
#!/usr/bin/expect -f
spawn su - target_user
expect "Password:"
send "password\r"
interact
For automated scripts where you need screen sessions as different users:
#!/bin/bash
# Start screen session as target user
sudo -u target_user bash -c "script -q -c 'screen -S session_name' /dev/null"