How to write three constantly updating lines in terminal using curses?

旧时模样 提交于 2021-02-10 06:09:35

问题


I have a program which needs to output three messages that are constantly changing. Number of connections, time elapsed, and refused connections.

I tried writing them with '\r' at the end of the string and printed newlines before the other ones started their own output loops thinking the return carriage goes back one line. but they all ended up in the first line overwriting each other.

I've seen similar questions and people were recommending using curses but i can't seem to get it to work. I try using addstr() instead of print or sys.stdout.write() but clearly i'm not doing it right because it ended up looking like this. I also tried using move(0,0) after every addstr because i thought that maybe the coordinates are calculated from the last position of the cursor but the output looked the same as when i didn't do it

Here's my current code using curses -

from scapy.all import *
from curses import wrapper 
import argparse, random, socket, sys, time, os, threading, re, subprocess, curses

def main(target):
    try: 
        stdscr.clear()
        curses.noecho()
        curses.cbreak()
        stdscr.keypad(1)

        #things regarding user agents and iptables

            for conn in range(args.connections):
                t = threading.Thread(target=sendPacket, args=(targetIP, args.port, targetHost,random.choice(userAgents)))
                threads.append(t)
                t.start()
                numConn += 1

                try:
                    lock.acquire()
                    stdscr.addstr(0, 0,'{0} Connections Established to {1} '.format(numConn,getIP(target)))
                    stdscr.refresh()
                    #sys.stdout.flush()
                finally:
                    lock.release()
            time.sleep(args.timer)  


        CloseWin()
        sys.exit()
    except KeyboardInterrupt, e:
        lock.acquire()
        stdscr.addstr (5,0,'Exiting {0}'.format(e))
        CloseWin()
        lock.release()
        sys.exit()

#functions that deal with resolving host and IP

def sendPacket(targetIP,targetPort,targetHost,userAgent):
    try:
        #building and sending the packet
        failPacket = 0
        lock.acquire()
        if synack is None:
            stdscr.addstr(1, 0, '{0} Connections refused'.format(failPacket))
            stdscr.refresh()
            failPacket += 1
            return

        #send final packet

        lock.release()
        return
    except Exception,e:
        CloseWin()
        #print e
        lock.release()
        return 



def MeasureTime():
try:
    lock.acquire()
    while True:
        stdscr.addstr(3, 0,'{0} Time elapsed'.format(time.time() - startTime))
        stdscr.refresh()
finally:
    lock.release()

def CloseWin():
try:
    lock.acquire()
    curses.nocbreak()
    stdscr.keypad(0)
    curses.echo()
    curses.endwin()
finally:
    lock.release()

if __name__ == '__main__':

    #args

    stdscr = curses.initscr()

    if args.debug == True:
        wrapper(OneConn(args.target)) #OneConn is the same as the main function except it only opens one connection, so the print is the same
    else:
        startTime = time.time()
        wrapper(main(args.target))

Also in addition to not writing correctly i can't seem to close it properly, when i use ctrl+c to try and get out it looks like it stops updating the print outs regarding the packet but the time still keeps going. and i can't figure out a way to stop it other than closing the terminal.

Tried adding locks per @martinaeu's suggestion and edited the post to show what i did. And the result was that i can only see the time elapsed being printed out and updated in the fourth line, can't see the other prints at all and still can't get out of the program without closing the terminal


回答1:


Instead of using curses, you can simply emit the raw codes to move the cursor back three lines. This would be:

os.write(1, "\x1b[3F")

Be careful: the lines are not erased. It shouldn't be a problem if the new lines that you print have the same length as the old ones (e.g. because they are formatted with something like "foo: %10d").

Reference: https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes (where "CSI" stands for "\x1b[" and the n is an optional number written in decimal).



来源:https://stackoverflow.com/questions/47498045/how-to-write-three-constantly-updating-lines-in-terminal-using-curses

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!