I want to redirect stdout and stderr to a socket that I can then use to remotely monitor the status of my application over Ethernet. Currently I accomplish this by using ssh and watching the output in the shell console. I'd prefer to remove the middle man if possible and just send the entire stdout and stderr output to a udp or tcp/ip port and have my monitoring computer connect to it.
I cannot use UART or any other wired connection. It has to be Ethernet. Also, if possible, I'd like to accomplish this via a bash script, to prevent having to rebuild my application.
Thanks for the help.
The way you describe it, it sounds like your going to need either your existing application to open a passive socket and wait for connections, or your going to have to wrap your application in something that sets up a listening socket. This post suggests that is not possible in just Bash, however it does show ways to do it from the command line with netcat or perl. For example you could do something like this with netcat: nc -l -p <port> -c "tail -F /var/log/blah"
On the monitored application side, there is a way to redirect both outputs to an outbound connection, using netcat:
$ ./application 2>&1 | nc <remote-host> <remote-port>
This way, you're redirecting stderr to stdout and then pipe it all together to netcat, which will take care of setting up the socket, establish connection with the remote host and all that stuff.
However, bear in mind that you can suffer from printf()'s buffering, if that's the function you're using to write to stdout. In my local tests, I've seen that the data sent to stderr by the application is seen immediately on the other listening end, but on the other hand the data sent to stdout is only sent when the application exits or there's enough data in the buffer to flush it all at once. So, if you care about the order and the availability of the info on the monitoring side, I'd suggest you to place calls to fflush(stdout); whenever you print something interesting to stdout, or replace the calls to printf(), fprintf() and the like to write(), which does not buffer. The downside is that you have to touch the code of the application, of course, but I don't know any way to externally force flushing of an application's output buffers (i.e. from bash).
Related
To give some context, I am trying to learn about pseudo-terminals (pty). A pseudo-terminal appears to a user process (bash for example) as if it was a real one. This allows to do all sorts of good stuff like telnet, ssh, etc.
My question is, for something like telnet, is it possible to just "exec" bash and set the stdin and stdout to be the tcp connection of the remote client machine. Because if that is possible, then I don't fully understand the value of using a pseudo-terminal
Yes, it's possible - and in fact this is how lots of "shellcode" exploits against network services traditionally gave the attacker a shell - but you won't be able to control it interactively to the extent you normally would. This is because a socket is not a tty. It can't translate bytes sent over the line into signals for the attached process (things like ^C, ^Z, etc.), it can't send EOFs as data, it can't do job control (suspend on ^Z, suspend on input when in background, etc.), and it can't convey mode switches (canonical/"cooked" mode versus raw mode).
I am wondering about the theoretical aspect of this. Say if I'm supposed to make something like an SSH, and I write commands on the client side. Initially I've created, bound, listened and connected sockets. Then I use the write() call for sending the command to a server.
Say ls is my command, and this is of my understanding and executable. I don't see how I can output and executable to a client, if I'm using read() on serverside and execute the ls. I can't simply store an ls in the write() call on serverside, in such a way that it on clientside could be read().
I am writing a client server program in C. The problem:
while server is listening and accepting new connections, it is also storing the IP's it is connected to. Now if we enter a command say LIST in the server program window which is still running, then it should display the list of IP's it is connected to ?
I am using the Select() function for each client.
In short, how to accept input from keyboard while answering the incoming connections?
Just include the file descriptor for standard input (STDIN_FILENO, aka 0) in the set of file descriptors passed into select(2). Then, if input is available for reading on that, you read from it and process the command; otherwise, process the sockets as usual.
Alternatively, you could run a separate thread to handle user input, but given that you already have the select call in place, it's probably easier to continue using that.
You may want to check out D.J. Bernstein's tcpserver (see http://cr.yp.to/ucspi-tcp/tcpserver.html). Basically, you can simply run your program under tcpserver, and tcpserver will handle everything as far as setting up the sockets, listing for incoming connections on whatever port you are using, etc. When an incoming connection arrives on the port that you specify, tcpserver will spawn an instance of your program and pipe incoming info from the client to your program's STDIN, and pipe outgoing info from your program's STDOUT back to the client. This way, you can concentrate on your program's core logic (and simply read/write to stdout/stdin), and let tcpserver handle all of the heavy lifting as far as the sockets, etc., and you can accept multiple simultaneous incoming connections this way.
As far as knowing the client ip's that are currently connected - this can be done at the command line by using netstat while the server is running.
I have a program that display the log output to the stdout.
So if I open a telnet session to my target linux and then launch on this telnet session my program then I will get the log messages displayed on my telnet session.
In my program I have a little http server running. Now if I change the IP address of my target linux and then I restart the interface (the http server will restart automatically because I detect the change of ip address with netlink) And then I will get the telnet session closed and the stdout messages are redirected to the socket opened by my http server and I will get the printf of the log message locked.
I tried with select to detect this lock but without success: How to use select with stdout?
The select return success before going to the prinf (which locks)
Any suggestion to avoid this problem ?
If I understand correctly, the telnet session (why aren't you using SSH??) under which the HTTP server is running becomes broken due to the change of IP address.
What will happen after that if the program continues to write data to this session (which is its stdout) is that, at first the writes will succeed as the system buffers up data, then eventually the writes will block (not "lock"). Finally, the TCP connection will time out and the writes will return an error. It may or may not take a long time for the TCP session to time out, but it eventually will.
You can make your log output code use non-blocking writes to stdout if you want to avoid blocking (e.g. if your application is event-driven and must not block). You will need to use fcntl to change stdout to non-blocking and you will probably need to avoid stdio altogether because stdio is not designed to work with non-blocking output. You must implement your own buffering and write directly to file descriptor 1.
You also mentioned that you want to log to an HTTP connection after the stdout log becomes broken. You could do that too (triggered once you get an error writing to stdout) but it will be a lot more work. You will have to manage your log buffer internally in your application until an HTTP client connects and requests it. You will also want to add a provision for discarding the log if it gets too big, in case no HTTP client connects. All of that is betyond the scope of a SO question...
I have to develop an application wherein I would receive data from parallel port and send it over to internet. This application is to be developed for embedded device running linux. Please suggest me how I can do that.
Regards
Sounds like a job for netcat. You can just open the device file and bind it straight to a TCP port: cat /dev/whatever | nc -l 2345 reads from a device and writes the results to a socket in case a client connects to port 2345.
If you need security, consider using a SSH tunnel.
Best solution - socat.
It can read from file and send to any socket (tcp, udp, unix, ipv4, ipv6), redirect program output, stdout. Reverse operations also posible.
Local example: read file "test", and send it content to localhost:9999
socat OPEN:test TCP:localhost:9999
If you want monitor file content and make it read only
socat OPEN:test,rdonly,ignoreeof TCP:localhost:9999
in socat you not need bash, in cat|nc some form of shell required.
I recommend sockets using C.
I would suggest either SSH or Telnet.
I would suggest using one of Perl, Python, or Ruby to do it if it has some processing to do.
Otherwise, if it is to use any console command, you can use curl or wget.
If you want to do it in C, perhaps because your embedded Linux doesn't have any of the shell tools and languages that other people have suggested, you need to look at the socket interface. The sequence of events is more or less:
create a socket using socket()
connect to a server using connect()
send your data using send(), or write() and deal with anything that comes back the other way using recv() or read().
close the socket using close().