Reading a config file
Well, here is how I'd write that subroutine. I thoroughly commented the code to explain my choices.

use strict;
use warnings;
use autodie;     # automatic error handling for "open" and other builtins
use IO::Handle;  # object oriented syntax for filehandles

# DEBUG is a compile-time constant initialized by an environment variable.
# If it is false, the debug statements will get optimized away.
use constant DEBUG =&gt; $ENV{DEBUG};

# the log file handle and debug file handle
# Here, I opened both to STDERR
open my $lfh, '&gt;&amp;', STDERR;
open my $dfh, '&gt;&amp;', STDERR;

# close the $lfh file handle regardless of how the script terminates.
END {
    no autodie;
    close $lfh or warn "Unable to close the log file handle: $!";
}

# the main part of our script
{
    my $filename = "config.txt";
    # "read_config_file" is a function that takes one argument and returns one value.
    my $config = read_config_file($filename);
    # if the check fails, exit this script with error code "1".
    # the default error code (zero) is considered a success.
    ui_check_config_ok(\*STDOUT, $config, $filename) or exit 1;

    # now we can do stuff with the $config, e.g.
    my $usr = $config-&gt;{username};
}

# Name your variables in snake_case, not with camelCase.
# This function *only* parses the config file.
# It does not interact with the user.
# Such separation of concern makes your code easier to maintain:
# every function should do one thing only.
sub read_config_file {
    # Subroutines can take an argument list.
    # We unpack it like this:
    my ($filename) = @_;

    $lfh-&gt;say("Reading config file $filename");
    DEBUG and $dfh-&gt;say("Opening config file $filename");

    my %known_keys = map { $_ =&gt; 1 } qw/
        username password subnet webserver imgFullSize imgThumSize
    /;

    # we wills store the config in this hash
    my %config;

    open my $fh, "&lt;", $filename;

    # don't slurp the file, we loop over it line by line
    LINE:
    while (&lt;$fh&gt;) {
        # trim the line
        s{\A\s+}{};
        s{\s+\z}{};

        DEBUG and $dfh-&gt;say("Reading line: $_");
        if (/^#/) {
            DEBUG and $dfh-&gt;say("Line is comment, skipping.");
            next LINE;
        }

        # * We use the /x flag on regexes to be able to structure the regex with spaces
        #   they won't match, they're just decoration
        # * instead of assigning to an array, we assign to a list of scalars.
        #   If the "split" fails, the last one should be "undef"
        # * We only accept one "=" per line, and produce 2 fragments max. So
        #       foo = bar = baz
        #   will produce $key="foo", $value="bar = baz".
        my ($key, $value) = split m{\s* [=] \s*}x, $_, 2;
        if (not defined $value) {
            DEBUG and $dfh-&gt;say("Ignoring config error: no key = value pair found on line: $_");
            next LINE;
        }

        DEBUG and $dfh-&gt;say("Value $key:$value");
        $config{$key} = $value;

        # a sanity check – you don't do anything on unknown keys
        if (not exists $known_keys{$key}) {
            $lfh-&gt;say("The config provided the unknown key $key, ignoring.")
        }
    }

    # another sanity check – did the user forget to specify some properties?
    for my $key (keys %known_keys) {
        if (not exists $config{$key}) {
            $lfh-&gt;say("The config didn't provide a key $key, ignoring.")
        }
    }

    return \%config;
}

# another subroutine that provides the user interface to ask whether the data is correct
# It will return a truth value whether the config was OK.
sub ui_check_config_ok {
    # Here, we see an argument list with three values
    my ($ui_fh, $config, $filename) = @_;

    $ui_fh-&gt;say($_) for
        "*********************************",
        "*Config imported",
        "*********************************",
        "*username    :$config-&gt;{username}",
        "*password    :$config-&gt;{password}",
        "*subnet      :$config-&gt;{subnet}",
        "*webserver   :$config-&gt;{webserver}",
        "*imgFullSize :$config-&gt;{imgFullSize}",
        "*imgThumSize :$config-&gt;{imgThumSize}",
        "*********************************";
    $ui_fh-&gt;print("Is this above correct?[Y]:");
    if (&lt;STDIN&gt; =~ /^\s*Y/) {
        $lfh-&gt;say("The user pressed Y. Config is good.");
        return 1;
    }

    $lfh-&gt;say("Config file contains false information, please correct.");
    $lfh-&gt;say("Terminating script");
    $ui_fh-&gt;say("The script will now terminate.");
    $ui_fh-&gt;say("Please amend the file $filename and rerun the script.");
    $ui_fh-&gt;say("Press any key to terminate...");
    &lt;&gt;;
    return 0;
}


Note how indentation made this code much easier to read than the dump you provided. Please use indentation!

I actually do not generally use IO::Handle, but it makes stuff more obvious when having more than one file handle. The autodie module is a bit inflexible, but I highly encourage it when you are still new with Perl, as it provides sensible defaults. You do not manually have to close file handles if they are variables declared with my – they will get closed automatically, and it's highly unlikely that closing a file will fail (file handles are not only used for physical files, but also for other things like pipes, where the close can fail).