Potential solution
After some research and experimenting, here's what I came up with:
logstuff(){
while true; do
case $1 in
"on" ) exec > >( ( printf ">>>>> TIME:$(date) SHELLPID:$$;\n"; tee /dev/tty ; printf ">>>>>\n" ) >> logfile.txt) 2>&1 ;
break;;
"off") exec > /dev/tty 2>&1 ;
break;;
*) echo "Please type 'on' or 'off';;
esac
done
}
This bash function should be placed in your ~/.bashrc and is available for use when opening new terminal or after issuing source ~/.bashrc. Logging has to be turned on manually via on and off arguments.
DEMO
Here's how it works in practice:
Do stuff in shell 1:
<shell 1>$ logstuff on
<shell 1>$ stat /etc/passwd
File: /etc/passwd
Size: 2208 Blocks: 8 IO Block: 4096 regular file
Device: 802h/2050d Inode: 156236 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2018-12-01 20:24:02.620000000 +0000
Modify: 2018-10-31 01:33:42.701000999 +0000
Change: 2018-10-31 01:33:42.704998999 +0000
Birth: -
<shell 1>$ logstuff off
<shell 1>$
Do stuff in shell 2:
< shell 2 >$ logstuff on
< shell 2 >$ echo "Hello World !"
Hello World !
< shell 2 >$ logstuff off
< shell 2 >$
Now review the logfile.txt:
<shell 1>$ cat logfile.txt
>>>>> TIME:Sat Dec 1 21:43:00 UTC 2018 SHELLPID:2225;
<shell 1>$ stat /etc/passwd
File: /etc/passwd
Size: 2208 Blocks: 8 IO Block: 4096 regular file
Device: 802h/2050d Inode: 156236 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2018-12-01 20:24:02.620000000 +0000
Modify: 2018-10-31 01:33:42.701000999 +0000
Change: 2018-10-31 01:33:42.704998999 +0000
Birth: -
<shell 1>$ >>>>> TIME:Sat Dec 1 21:43:11 UTC 2018 SHELLPID:2359;
< shell 2 >$ echo "Hello World !"
Hello World !
< shell 2 >$ logstuff off
>>>>>
logstuff off
>>>>>
<shell 1>$
Issues
- If
logstuff on is issued in both terminals first, there's a chance of outputs being mangled together. The way it works is that you have to issue logsutff on in shell 1, then issue commands there, then issue logstuff on in shell 2.
- This uses process substitution
>( ), tee and a subshell. Not the most elegant nor efficient due to bunch of forking and extra pipeline.
logfile.txt is stored in current working directory. This should be changed to ~/logfile.txt or however the user sees fit.
Practical considerations
What the question itself asks is somewhat impractical: storing output from multiple shells into one single file means you're storing output of commands from two or more completely unrelated session, which may have different environment variables, different working directories, or working on different filesystems; this means there's whole lot of context lacking if you're intending to use such log text for debugging purposes or solving a problem.
Far better approach would be to have script -f write to log files in one specific directory, potentially with filenames of such logs timestamped or appended the shell PID. Another solution - instead of having 3 different terminals, just use one - screen or my personal favorite byobu-screen. You can attach/detach to a single virtual tty session in screen and it is often used to keep processes running on remote servers where you have to log out but still need a shell session with output and tracebacks running. This can be combined with script as well.