In zsh, when you redirect a fd more than once for output, zsh does the forking internally, so you'd do:
echo hi >&1 >&2
To output both to stdout and stderr.
Though, if you wanted to output it to both test.out and test.err, you'd do:
echo hi > test.out > test.err
instead.
On systems other than Linux based ones and Cygwin, you can do the same with
echo hi | tee /dev/stderr
On Linux and Cygwin, that's wrong though unless stderr happens to be opened on a pipe or tty as opening /dev/stderr opens the file pointed to by stderr (fd 2) anew, so for instance if stderr was being redirected to a log file, that would replace the log file with that hi line, and if stderr was opened to a socket, that would fail as sockets can't be opened.
Adding the -a option to tee (for append mode) can help with the case of a log file.
Another work around with shells with process substitution support is to use:
echo hi | tee >(cat >&2)
But that also comes with its own problems, like the fact that in some shells such as bash, that cat command is not waited for, so you can see this kind of problem:
$ bash -c 'echo hi | tee >(cat >&2); echo after >&2' hi after hi
Where echo after is being run before cat has had time to write hi.