Write a Bash Shell Script That Consumes a Constant Amount of Ram for a User Defined Time

Write a bash shell script that consumes a constant amount of RAM for a user defined time

Even if traditional Bash arrays are not supported, it may still be possible to create array-like variables using the eval command built into the particular shell.

The following example script is based on some scripting I did when using BusyBox in an embedded Linux project. BusyBox uses the Almquist shell (also known as A Shell, ash, and sh), which does not support arrays.

#!/bin/ash

for index in 1 2 3 4 5; do
value=$(($index * 1024))
eval array$index=\"array[$index]: $value\"
done

for i in 1 3 5; do
eval echo \$array$i
done

Be careful with quoting when using eval!

Output:

array[1]: 1024
array[3]: 3072
array[5]: 5120

Depending on your particular scenario, a script similar to the following may suffice.

#!/bin/ash

echo "Provide sleep time in the form of NUMBER[SUFFIX]"
echo " SUFFIX may be 's' for seconds (default), 'm' for minutes,"
echo " 'h' for hours, or 'd' for days."
read -p "> " delay

echo "begin allocating memory..."
for index in $(seq 1000); do
value=$(seq -w -s '' $index $(($index + 100000)))
eval array$index=$value
done
echo "...end allocating memory"

echo "sleeping for $delay"
sleep $delay

In my brief testing, this script consumed ~570M to ~575M physical memory* for the specified time period of 5 minutes.

* Monitored using top and memprof programs in separate tests

Rather high CPU usage with memory monitoring bash script


Any idea what's causing this and how I can optimize it?

The line

sleep 5

is inside the condition that checks whether the memory is within the specified range. Chances are that most of the times that memory isn't within this range, which causes the infinite loop without any sleep whatsoever and makes the script consume more resources than you'd expect it to.

Take the line outside the if loop and that should help.

how to eat up all the android memory in an android application?

Since you are able to use ADB and have busybox you may be able to use a shell script that allocates memory until it's exhausted.

refer to Write a bash shell script that consumes a constant amount of RAM for a user defined time

ripped from that answer:

#!/bin/ash

echo "Provide sleep time in the form of NUMBER[SUFFIX]"
echo " SUFFIX may be 's' for seconds (default), 'm' for minutes,"
echo " 'h' for hours, or 'd' for days."
read -p "> " delay

echo "begin allocating memory..."
for index in $(seq 1000); do
value=$(seq -w -s '' $index $(($index + 100000)))
eval array$index=$value
done
echo "...end allocating memory"

echo "sleeping for $delay"
sleep $delay

How do I iterate over a range of numbers defined by variables in Bash?


for i in $(seq 1 $END); do echo $i; done

edit: I prefer seq over the other methods because I can actually remember it ;)

Retrieve CPU usage and memory usage of a single process on Linux?


ps -p <pid> -o %cpu,%mem,cmd

(You can leave off "cmd" but that might be helpful in debugging).

Note that this gives average CPU usage of the process over the time it has been running.

Limit memory usage for a single Linux process

There's some problems with ulimit. Here's a useful read on the topic: Limiting time and memory consumption of a program in Linux, which lead to the timeout tool, which lets you cage a process (and its forks) by time or memory consumption.

The timeout tool requires Perl 5+ and the /proc filesystem mounted. After that you copy the tool to e.g. /usr/local/bin like so:

curl https://raw.githubusercontent.com/pshved/timeout/master/timeout | \
sudo tee /usr/local/bin/timeout && sudo chmod 755 /usr/local/bin/timeout

After that, you can 'cage' your process by memory consumption as in your question like so:

timeout -m 500 pdftoppm Sample.pdf

Alternatively you could use -t <seconds> and -x <hertz> to respectively limit the process by time or CPU constraints.

The way this tool works is by checking multiple times per second if the spawned process has not oversubscribed its set boundaries. This means there actually is a small window where a process could potentially be oversubscribing before timeout notices and kills the process.

A more correct approach would hence likely involve cgroups, but that is much more involved to set up, even if you'd use Docker or runC, which among things, offer a more user-friendly abstraction around cgroups.



Related Topics



Leave a reply



Submit