The problem is surprisingly more complicated than most people would expect.
The short answer is that you need to use init, or write a replacement for init that implements reaping and downstream signals propagation, or find a new way to pass data to mysqld, or find a way to live with it (which requires understanding and limiting your zombie creation rate).
zombie processes arise when their exit status is not collected (reaped) by the parent.
exec replaces the current process (a shell) with mysqld, which is not expecting to inherit child processes.
If you start mysqld in the background, and let the shell script remain to reap children, it also needs to handle propagating received signals to mysqld and waiting for them to respond. Failing to do so will cause mysql to be un-gracefully terminated when the shell script exits. This reaping and propagation is normally the job of
You can make the echo exit immediately by opening a handle for read, like this:
echo "something" > /tmp/fifo &
exec 3< /tmp/fifo
... but that creates a new problem: normally
echo would close the fifo, and now it can't: it exits too soon. That means mysql will block when reading it. It's possible to do non-blocking reads and implement timeouts and all that, but we can assume mysql doesn't, because it probably expects
--init-file to behave like a regular file.
The last option is to live with it. If we're talking about 1 process or 100, that's fine. But the process table is finite and each zombie consumes an entry in it. If you don't manage the zombie count, and the process table fills, you can't create any new processes.
The blog post I linked has a lot of good detail and plugs a small init replacement, created by the author, to solve your exact problem.