init script '/dev/tty: No such device or address' error on redirect

bash, linux, shell, stderr, variables

Solution

Rather than writing to `/dev/tty`, how about simply swapping stdout and stderr?

yourcommand 3>&2 2>&1 1>&3 3>&-

This is the redirection equivalent of swapping the contents of two variables using a third temporary variable:

3>&2  # tmp = stderr 
2>&1  # stderr = stdout
1>&3  # stdout = tmp
3>&-  # close(tmp)

Problem

I will include the entire script at the bottom for reference. This script gets called toward the end of the init scripts. If I run the script after logging in, it runs with no error. 30000 foot view, trying to execute a rsync command and capture any errors into a variable. I am using bash 3.5.6pl. Here is the line that is the culprit: ``` LogMessage+=$(rsync -rpltDzv --delete --progress /mnt/WinPrimary /mnt/WinBackup 2>&1 >/dev/tty)$'\n' ``` What is stored in the variable, which does get written to a log, is: ``` /etc/Braums/scripts/Sync1to2.sh: line 47: /dev/tty: No such device or address ``` I googled the technique for the syntax to capture stderr but not stdout. I want the progress to show and not capture all the screen stuff. So the init calls the script “Sync1to2.sh”. Which has the above command. If I run the same script from the command line after logging in, it runs as expected. Here is the entire Sync1to2.sh script. I don’t do bash scripts too often, so be careful and don’t hurt yourself laughing. One other note, below is when I tried /dev/stdout and it has some diagnostic. I betting it has something to when getty is ran? ``` #!/bin/bash # #Variable to set if an error occurs at any point during the process. ErrorOccured="False" LogMessage="" LogMessage+=$0$' was stated at '$(date)$'\n' if !(mount | grep -cq "/mnt/WinPrimary") then LogMessage+=$'=============================================\n' LogMessage+=$'][ No Windows Primary found. ][\n' LogMessage+=$'][ Check drives and try again. ][\n' LogMessage+=$'=============================================\n' ErrorOccured="True" fi if !(mount | grep -cq "/mnt/WinBackup") then LogMessage+=$'=============================================\n' LogMessage+=$'][ No Windows Backup found. ][\n' LogMessage+=$'][ Check drives and try again. ][\n' LogMessage+=$'=============================================\n' ErrorOccured="True" fi if test "$ErrorOccured" == "False" then #Maybe add cleanup the harddrive later if [ -f /mnt/WinPrimary/Sync1to2.err ] then LogMessage+=$'=============================================\n' LogMessage+=$'][ Found a Sync1to2.err. ][\n' LogMessage+=$'][ Are we being run in a loop? ][\n' LogMessage+=$'=============================================\n' ErrorOccured="True" fi if [ -f /mnt/WinPrimary/Sync1to2.ok ] then LogMessage+=$'=============================================\n' LogMessage+=$'][ Found a Sync1to2.ok. ][\n' LogMessage+=$'][ Are we being run in a loop? ][\n' LogMessage+=$'=============================================\n' ErrorOccured="True" fi if [ "$ErrorOccured" == "False" ] then LogMessage+=$'Sync Started '$(date)$'\n' LogMessage+=$(rsync -rpltDzv --delete --progress /mnt/WinPrimary /mnt/WinBackup 2>&1 >/dev/stdout)$'\n' ExitValue=$? LogMessage+=$'Sync Finished '$(date)$'\n' LogMessage+=$'____________________ '$(date)$'\n' LogMessage+=$(ls /dev/tty*)$'\n' LogMessage+=$'____________________ '$(date)$'\n' LogMessage+=$'____________________ '$(date)$'\n' LogMessage+=$(ls /dev/stdout)$'\n' LogMessage+=$'____________________ '$(date)$'\n' if [ $ExitValue != 0 ] then ErrorOccured="True" fi fi fi echo $ErrorOccured if [ "$ErrorOccured" == "True" ] then echo "Sync1to2 errored out" >> /mnt/WinPrimary/Sync1to2.err echo "_______________________________________________________" >> /mnt/WinPrimary/Sync1to2.err echo "Finished $(date)" >> /mnt/WinPrimary/Sync1to2.err echo "$LogMessage" >> /mnt/WinPrimary/Sync1to2.err echo "_______________________________________________________" >> /mnt/WinPrimary/Sync1to2.err else echo "Sync1to2 ok" >> /mnt/WinPrimary/Sync1to2.ok echo "_______________________________________________________" >> /mnt/WinPrimary/Sync1to2.ok echo "Finished $(date)" >> /mnt/WinPrimary/Sync1to2.ok echo "$LogMessage" >> /mnt/WinPrimary/Sync1to2.ok echo "_______________________________________________________" >> /mnt/WinPrimary/Sync1to2.ok cp /mnt/WinPrimary/menu.default.lst /mnt/WinPrimary/menu.lst cp /mnt/WinPrimary/menu.default.lst /mnt/WinBackup/menu.lst echo Shuting down fi /etc/Braums/scripts/LogPing.pl Sync1to2 "$LogMessage" exit 254 ```

Original source