Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Starting an interactive shell in Linux
Forum Updated to NodeBB v4.3 + New Features

Starting an interactive shell in Linux

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 3 Posters 1.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    pingal
    wrote on last edited by
    #1

    I've client/server app in which I want to start an interactive shell/terminal on client side upon request from server. Is their a generic utility which works as an interactive shell on all major Linux systems for example, sh utility in linux ?

    Should i use QProcess to start sh and then try to read/write to its STD I/O or is their another way to achieve interactive shell behaviour?

    Thanks

    JonBJ 1 Reply Last reply
    0
    • P pingal

      I've client/server app in which I want to start an interactive shell/terminal on client side upon request from server. Is their a generic utility which works as an interactive shell on all major Linux systems for example, sh utility in linux ?

      Should i use QProcess to start sh and then try to read/write to its STD I/O or is their another way to achieve interactive shell behaviour?

      Thanks

      JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by
      #2

      @pingal
      /bin/sh is always available under Linux, if that is what you mean.

      If you need/want to interact with a program you spawn, in the sense of writing to its input and/or reading from its output, then yes use QProcess and you can do that (per the docs).

      Whether that applies to your "interactive shell/terminal" is another matter. sh won't show any window to the user anyway. What is your "interactivity", what are you actually needing to do?

      P 1 Reply Last reply
      0
      • JonBJ JonB

        @pingal
        /bin/sh is always available under Linux, if that is what you mean.

        If you need/want to interact with a program you spawn, in the sense of writing to its input and/or reading from its output, then yes use QProcess and you can do that (per the docs).

        Whether that applies to your "interactive shell/terminal" is another matter. sh won't show any window to the user anyway. What is your "interactivity", what are you actually needing to do?

        P Offline
        P Offline
        pingal
        wrote on last edited by
        #3

        @JonB

        The purpose is to get the /bin/sh interface of the client so that server user can interact with the client shell remotely. Just like someone login to a remote machine using ssh, for example.

        JonBJ 1 Reply Last reply
        0
        • P pingal

          @JonB

          The purpose is to get the /bin/sh interface of the client so that server user can interact with the client shell remotely. Just like someone login to a remote machine using ssh, for example.

          JonBJ Online
          JonBJ Online
          JonB
          wrote on last edited by JonB
          #4

          @pingal
          Yes, sh functions like ssh. But I'm still not clear what you want the "interactivity" for. Neither one opens any kind of "visual window" of their own. You have two basic ways you can drive them:

          • You can run them in a terminal, such as xterm. That will open an X window. The user can then sit in front of it, type commands, and see the output. But in that "interactivity" your Qt application cannot send commands and "see" the output, only the user sitting there can.

          • You can run them directly from your Qt program. But that will not open any window for the user to see/interact with. Your Qt application can send commands to it by writing to its stdout on QProcess which will arrive at the shell's stdin, and can collect what the shell writes to its stdout/stderr and then show it to the user e.g. in a widget. But your Qt program has to do this writing & reading for each command. At which point, it is not clear that you really want an "interactive" shell at all. You might just as well send each command and receive its output each time, without leaving any "interactive shell" running at all. In the case of ssh it might be worth it because of the overhead of having to "authenticate" each time, but sh really does not do a lot for you. You might even send the commands directly without an interposing sh, depending on what the commands are.

          I suppose I ought to have verified from the beginning: is your Qt program a UI one, with windows and widgets, or is it just a command-line one, with no UI widgets? If it is the latter you would run it from a terminal (e.g. xterm).

          P 1 Reply Last reply
          0
          • JonBJ JonB

            @pingal
            Yes, sh functions like ssh. But I'm still not clear what you want the "interactivity" for. Neither one opens any kind of "visual window" of their own. You have two basic ways you can drive them:

            • You can run them in a terminal, such as xterm. That will open an X window. The user can then sit in front of it, type commands, and see the output. But in that "interactivity" your Qt application cannot send commands and "see" the output, only the user sitting there can.

            • You can run them directly from your Qt program. But that will not open any window for the user to see/interact with. Your Qt application can send commands to it by writing to its stdout on QProcess which will arrive at the shell's stdin, and can collect what the shell writes to its stdout/stderr and then show it to the user e.g. in a widget. But your Qt program has to do this writing & reading for each command. At which point, it is not clear that you really want an "interactive" shell at all. You might just as well send each command and receive its output each time, without leaving any "interactive shell" running at all. In the case of ssh it might be worth it because of the overhead of having to "authenticate" each time, but sh really does not do a lot for you. You might even send the commands directly without an interposing sh, depending on what the commands are.

            I suppose I ought to have verified from the beginning: is your Qt program a UI one, with windows and widgets, or is it just a command-line one, with no UI widgets? If it is the latter you would run it from a terminal (e.g. xterm).

            P Offline
            P Offline
            pingal
            wrote on last edited by pingal
            #5

            @JonB

            I've spawned /bin/sh as a QProcess and commands I receives from server app is being written to it and output is read from it and send to server accordingly. So this somehow mimic interactivity and it works.

            The problem I'm facing now is when i write "exit" to the spawned process (i.e. /bin/sh) from my client app, it exit my whole client app.

            Here is how i'm spawning and writing command(s) to it

            if(shell == nullptr){     // If the shell is not running, spawn it 
                shell = new QProcess(this);
            
            #if defined (__linux__) || defined (__unix__)
                        QString pathToShell("/bin/sh");
            #endif
                QObject::connect(shell, &QProcess::started, this, [](){qDebug() << "/bin/sh started";});
                QObject::connect(shell, &QProcess::readyRead, this, [this](){emit sendToServer(shell->readAllStandardOutput());});
                connect(shell, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
                            [this](int exitCode, QProcess::ExitStatus exitStatus){ qDebug()<< QFileInfo(shell->program()).fileName() << "is finished with Exit Code:"<< exitCode << " ExitStatus:"<< exitStatus; shell->deleteLater();shell=nullptr;});
                shell->start(pathToShell);
            
            }
                // If shell is running, Submit commands to its STDIN
            if(!RecievedCommand.isEmpty() && shell != nullptr){
                    RecievedCommand.append("\n");
                    shell->write(RecievedCommand.toStdString().c_str());
            }
            
            jsulmJ JonBJ 2 Replies Last reply
            1
            • P pingal

              @JonB

              I've spawned /bin/sh as a QProcess and commands I receives from server app is being written to it and output is read from it and send to server accordingly. So this somehow mimic interactivity and it works.

              The problem I'm facing now is when i write "exit" to the spawned process (i.e. /bin/sh) from my client app, it exit my whole client app.

              Here is how i'm spawning and writing command(s) to it

              if(shell == nullptr){     // If the shell is not running, spawn it 
                  shell = new QProcess(this);
              
              #if defined (__linux__) || defined (__unix__)
                          QString pathToShell("/bin/sh");
              #endif
                  QObject::connect(shell, &QProcess::started, this, [](){qDebug() << "/bin/sh started";});
                  QObject::connect(shell, &QProcess::readyRead, this, [this](){emit sendToServer(shell->readAllStandardOutput());});
                  connect(shell, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
                              [this](int exitCode, QProcess::ExitStatus exitStatus){ qDebug()<< QFileInfo(shell->program()).fileName() << "is finished with Exit Code:"<< exitCode << " ExitStatus:"<< exitStatus; shell->deleteLater();shell=nullptr;});
                  shell->start(pathToShell);
              
              }
                  // If shell is running, Submit commands to its STDIN
              if(!RecievedCommand.isEmpty() && shell != nullptr){
                      RecievedCommand.append("\n");
                      shell->write(RecievedCommand.toStdString().c_str());
              }
              
              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @pingal said in Starting an interactive shell in Linux:

              it exit my whole client app

              Should not happen. Did you debug your client app to see what exactly happens? Maybe it is crashing?

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              P 1 Reply Last reply
              0
              • jsulmJ jsulm

                @pingal said in Starting an interactive shell in Linux:

                it exit my whole client app

                Should not happen. Did you debug your client app to see what exactly happens? Maybe it is crashing?

                P Offline
                P Offline
                pingal
                wrote on last edited by
                #7

                @jsulm Thanks for helpful advices.

                It works fine now.

                1 Reply Last reply
                0
                • P pingal

                  @JonB

                  I've spawned /bin/sh as a QProcess and commands I receives from server app is being written to it and output is read from it and send to server accordingly. So this somehow mimic interactivity and it works.

                  The problem I'm facing now is when i write "exit" to the spawned process (i.e. /bin/sh) from my client app, it exit my whole client app.

                  Here is how i'm spawning and writing command(s) to it

                  if(shell == nullptr){     // If the shell is not running, spawn it 
                      shell = new QProcess(this);
                  
                  #if defined (__linux__) || defined (__unix__)
                              QString pathToShell("/bin/sh");
                  #endif
                      QObject::connect(shell, &QProcess::started, this, [](){qDebug() << "/bin/sh started";});
                      QObject::connect(shell, &QProcess::readyRead, this, [this](){emit sendToServer(shell->readAllStandardOutput());});
                      connect(shell, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
                                  [this](int exitCode, QProcess::ExitStatus exitStatus){ qDebug()<< QFileInfo(shell->program()).fileName() << "is finished with Exit Code:"<< exitCode << " ExitStatus:"<< exitStatus; shell->deleteLater();shell=nullptr;});
                      shell->start(pathToShell);
                  
                  }
                      // If shell is running, Submit commands to its STDIN
                  if(!RecievedCommand.isEmpty() && shell != nullptr){
                          RecievedCommand.append("\n");
                          shell->write(RecievedCommand.toStdString().c_str());
                  }
                  
                  JonBJ Online
                  JonBJ Online
                  JonB
                  wrote on last edited by
                  #8

                  @pingal
                  Your code is good. However you have not connected to read anything written on standard error in the shell, and you should certainly do so! Either call as well shell->readAllStandardError() in your readyRead() slot and/or use QProcess::readReadStandardOutput/Error() signals instead of readyRead(), or use setProcessChannelMode(QProcess::MergedChannels).

                  P 1 Reply Last reply
                  2
                  • JonBJ JonB

                    @pingal
                    Your code is good. However you have not connected to read anything written on standard error in the shell, and you should certainly do so! Either call as well shell->readAllStandardError() in your readyRead() slot and/or use QProcess::readReadStandardOutput/Error() signals instead of readyRead(), or use setProcessChannelMode(QProcess::MergedChannels).

                    P Offline
                    P Offline
                    pingal
                    wrote on last edited by
                    #9

                    @JonB Yes, that's what i missed ! Thanks for the reminder.

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved