views:

836

answers:

1

Hi! I'm running a few Team Fortress 2 servers and I want to write a little management script.

Basically the TF2 servers are a fg process which provides a server console, so I can start the server, type status and get an answer from it:

***@purple:~/tf2$ ./start_server_testing 
Auto detecting CPU
Using AMD Optimised binary.
Server will auto-restart if there is a crash.

Console initialized.
[bla bla bla]
Connection to Steam servers successful.
   VAC secure mode is activated.

status

hostname: Team Fortress
version : 1.0.6.1/15 3883 secure
udp/ip  :  ***.***.133.31:27600
map     : ctf_2fort at: 0 x, 0 y, 0 z
players : 0 (2 max)

# userid name uniqueid connected ping loss state adr

Great, now I want to create a script which sends the command sm_reloadadmins to all my servers. The best way I found to do this is using a fifo named pipe. Now what I want to do is having this pipe readonly and non blocking to the server process, so I can write into the pipe and the server executes it, but still I want to write via console one the server, so if I switch back to the fg process of the server and I type status I want an answer printed.

I tried this (assuming serverfifo is mkfifo serverfifo):

./start_server_testing < serverfifo

Not working, the server won't start until something is written to the pipe.

./start_server_testing <> serverfifo

Thats actually working pretty good, I can see the console output of the server and I can write to the fifo and the server executes the commands, but I can't write via console to the server anymore. Also, if I write 'exit' to the pipe (which should end the server) and I'm running it in a screen the screen window is getting killed for some reason (wtf why?).

I only need the server to read the fifo without blocking AND all my keyboard input on the server itself should be send to the server AND all server ouput should be written to the console.

Is that possible? If yes, how?

A: 

I realize this isn't an answer in the same vein as you were pursuing, but you can probably do this using Gnu Screen.

Screen is a program that makes a pseudo-TTY. You can use its ability to let you share a screen session. This way, you can be logged in to the server inside of screen, and your script can share that session, send a command which you can see, and then stop sharing. The process to get screen set up to allow sharing sessions is described here. It requires root access, but I'm presuming you have that if you're running a TF2 server.

Once you get the setuid process set up and have the server prompt inside of screen, you can have your script log in to the relevant box, connect to screen, send the desired command to the server, send Ctrl-A,d to disconnect from screen, and then logout.

Conspicuous Compiler
I am actually using a screen in which I run all of my servers (CTRL+A,c created windows in one screen). I also wrote that:`[...]and I'm running it in a screen the screen window is getting killed for some reason (wtf why?).[...]`But now, can I write into the screen maybe? I know, if I create a new screen I can somehow send a command that is executed by the screen and then detach, but can I send a command to an existing screen?
timdel
No wait, I think using a pipe to send text to a process is still a better idea than sending it to the screen.
timdel
Ah. I failed to understand what you were saying in that paragraph. The fact that you're using screen already makes matters easier.In answer to your question "can I send a command to an existing screen?", my answer was explaining exactly how you would go about that process. Where was I unclear?
Conspicuous Compiler
It's not the answer to my problem. I want an automated script so I can type./reloadadminsand it just sends sm_reloadadmins to the server's process.In fact, I'm using multiple windows in one screen session, and as far as I know a script can only pass a command to the active window in a screen session.Anyways, I want to send the command sm_reloadadmins not to one server, but to ALL of my servers.So I don't think screen is a good / the best solution for my problem, so I'll just stay at named pipes.
timdel
I realize that this isn't the way you were attemping to solve your problem. However, what you are attemping to do is have multiple input streams to one process, for which there is no easy way to do in bash. The command you have provided above redirects both input and output to come from your fifo, which will make console interaction impossible. -- As far as multiple servers, you can just as easily have a script log in on server as multipe by coding it to repeat the process. Similarly, you could have it send the command (Ctrl A,1) to switch windows upon logging in...
Conspicuous Compiler
...But it doesn't sound like you're open to exploring alternatives. Best of luck.
Conspicuous Compiler
I'm very open for alternatives, but using the screen I/O is imo very very very instable, because I never know in which window of my screen is running a server or which server (it's not as static as a named pipe). If I use a named pipe I can eg. create a pipe for every server, so I know exactly to which server I'm writing currently to. I need this to seperate the private servers from the public servers.Also I noticed that <> is remapping my stdio (I added a command to my post a few minutes ago concerning this. So what I need is a solution to map stdout to the console ...
timdel
... and stdin to both, my keyboard and the named pipe.
timdel