Remotely Control your Linux Terminal through Flutter Application.

Rohit Mittal
4 min readDec 17, 2020

Why need of Terminal?

The Terminal provides an efficient interface to access the true power of a computer better than any graphical interface.
With this terminal application, you can remotely manage your Linux machine that may be installed on your host machine or an EC2 instance of AWS.

Requirements:

  1. Web Server (Apache HTTPD in this case) installed in Linux(RHEL-8 in this case).
  2. Python3 with CGI package
  3. Flutter installed in Android Studio

Let's prepare our Linux Environment:

  1. Configure yum in RHEL-8(GUI):

#cd /etc/yum.repos.d/
#cat >> rohit.repo
[dvd1]
baseurl=file:///run/media/root/RHEL-8–0–0-BaseOS-x86_64/AppStream
gpgcheck=0
[dvd2]
baseurl=file:///run/media/root/RHEL-8–0–0-BaseOS-x86_64/BaseOS
gpgcheck=0

2. Install and configure the HTTPD server in RHEL-8:
◘ First step is to use the dnf the command to install the package called httpd:

# dnf install httpd

◘ Run and enable the Apache webserver to start after reboot:

# systemctl enable httpd
# systemctl start httpd

◘ Optionally, if you need your Apache HTTPD web server to be accessed from remote locations open HTTP firewall port 80:

# firewall-cmd --zone=public --permanent --add-service=http
# firewall-cmd --reload

◘ Insert your website files.

By default, the Apache webserver will greet you with a default welcome page. To disable the default Apache welcome page insert your index.html into /var/www/html/ directory.

◘ Access your website.

To access your new sample website navigate your web browser to http://YOUR-IP-ADDRESS

If you get a web page you have created with index.html or Apache welcome page then you have successfully configured the webserver.

Check the status of the Server.

3. Install CGI and SUBPROCESS packages using pip3:

#pip3 install cgi
#pip3 install subprocess

4. Create a file named terminal.py in /var/www/cgi-bin :

mode to cgi-bin

make and edit the file using gedit (it is a graphical tool in RHEL-8 to create and edit file):

#gedit terminal.pywrite these lines into terminal.py:#!/usr/bin/python3import cgi
import subprocess
print("context-type: text/html")
print()
mydata = cgi.FieldStorage()
myx = mydata.getvalue("x");
output = subprocess.getoutput(myx)
print(output)

make the file executable:

#chmod +x terminal.py

Start Creating Flutter application:

To connect over a network we need an HTTP protocol, so we require our application to support HTTP, for that we have to install the HTTP package in our pubspec.yaml file and import it in our dart file.

You can install it by mentioning HTTP and version in the dependencies section like this:

name: linux_cgi
description: A new Flutter application.

publish_to: 'none'
version: 1.0.0+1
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
http: ^0.12.2
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.0
dev_dependencies:
flutter_test:
sdk: flutter
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true

Check here for references or to resolve errors(if any).

In the main.dart file paste the code given below and change the IP with the IP address of your Linux machine.

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
main() {
runApp(terminal());
}
// ignore: camel_case_types
class terminal extends StatefulWidget {
@override
_terminalState createState() => _terminalState();
}
// ignore: camel_case_types
class _terminalState extends State<terminal> {
var input;
var output;
web(input) async {
var url = "http://IP/cgi-bin/terminal.py?x=$input";
var response = await http.get(url);
setState(() {
output = response.body;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: Scaffold(
resizeToAvoidBottomInset: false,
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text("Terminal"),
),
body: Container(
child: Card(
child: Column(
children: [
TextField(
onChanged: (value) {
input = value;
},
onSubmitted: (value) {
web(input);
},
autofocus: true,
cursorColor: Colors.white,
cursorWidth: 2.0,
decoration: InputDecoration(
hintText: "Enter Linux Command",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
borderSide: BorderSide(
color: Colors.amber,
style: BorderStyle.solid,
),
),
),
),
RaisedButton(
onPressed: () {
web(input);
},
child: Text("Run cmd"),
),
Container(
height: 450,
child: ListView(
scrollDirection: Axis.vertical,
children: [Text(output ?? '')],
),
),
],
),
),
)),
);
}
}

Now run the application on your device to check if it is working fine.

It will generate an interface like this:

Initial Interface
Try running any Linux command
Try running any Linux Command.

Hurray! Now you are accessing your Terminal on your flutter application.

Don’t Quit

For any doubts, ideas or queries feel free to reach me on:

1. LinkedIn

2. GitHub

3. Twitter

Useful Links and Articles:

1. pub.dev to download packages.
2. Linux package management with YUM and RPM

Please leave comments, feedback, and suggestions as I am always trying to improve.
Share your thoughts — it’s never been easier 😄

--

--

Rohit Mittal

I am an enthusiastic engineer, seeking an opportunity where I can explore, evolve, learn and at same time contribute to the goals of an organization.